- 11/04/2016
- 3 minutos para leer
-
- c
- v
- n
- M
- g
-
+1
Una declaración de función precede a la definición de la función y especifica el nombre, tipo de retorno, clase de almacenamiento y otros atributos de una función. Para ser un prototipo, la declaración de función también debe establecer tipos e identificadores para los argumentos de la función.
Sintaxis
declaración:
especificadores de declaración attribute-seqopt init-declarator-listopt ;
/* attribute-seqopt es específico de Microsoft */
especificadores de declaración:
especificador de clase de almacenamiento declaración-especificadoresopt
especificador de tipo declaración-especificadoresopt
especificador de tipo declaración-especificadoresopt
init-declarator-list:
init-declarator
init-declarator-list , init-declarator
init-declarator:
declarator
declarator = initializer
declarator:
pointeropt direct-declarator
direct-declarator: /* Un declarador de función */
declarador-directo («parameter-type-list») /* Declarador de estilo nuevo */
declarador-directo («identifier-listopt») /* Declarador de estilo obsoleto */
El prototipo tiene la misma forma que la definición de función, excepto que se termina con un punto y coma inmediatamente después del paréntesis de cierre y, por tanto, no tiene cuerpo. En cualquier caso, el tipo de retorno debe coincidir con el tipo de retorno especificado en la definición de la función.
Los prototipos de función tienen los siguientes usos importantes:
-
Establecen el tipo de retorno para las funciones que devuelven tipos distintos de
int
. Aunque las funciones que devuelven valoresint
no requieren prototipos, se recomiendan los prototipos. -
Sin prototipos completos, se realizan conversiones estándar, pero no se intenta comprobar el tipo o el número de argumentos con el número de parámetros.
-
Los prototipos se utilizan para inicializar punteros a funciones antes de que éstas se definan.
-
La lista de parámetros se utiliza para comprobar la correspondencia de los argumentos en la llamada a la función con los parámetros en la definición de la función.
El tipo convertido de cada parámetro determina la interpretación de los argumentos que la llamada a la función coloca en la pila. Un desajuste de tipo entre un argumento y un parámetro puede hacer que los argumentos en la pila sean malinterpretados. Por ejemplo, en un ordenador de 16 bits, si se pasa un puntero de 16 bits como argumento y luego se declara como parámetro long
, los primeros 32 bits de la pila se interpretan como un parámetro long
. Este error crea problemas no sólo con el parámetro long
, sino con cualquier parámetro que le siga. Puede detectar errores de este tipo declarando prototipos de función completos para todas las funciones.
Un prototipo establece los atributos de una función para que las llamadas a la función que preceden a su definición (o que se producen en otros archivos fuente) puedan ser comprobadas en busca de desajustes de tipo de argumento y de tipo de retorno. Por ejemplo, si especifica el especificador de clase de almacenamiento static
en un prototipo, también debe especificar la clase de almacenamiento static
en la definición de la función.
Las declaraciones de parámetros completos (int a
) pueden mezclarse con declaradores abstractos (int
) en la misma declaración. Por ejemplo, la siguiente declaración es legal:
int add( int a, int );
El prototipo puede incluir tanto el tipo de, como un identificador para, cada expresión que se pasa como un argumento. Sin embargo, estos identificadores sólo tienen alcance hasta el final de la declaración. El prototipo también puede reflejar el hecho de que el número de argumentos es variable, o que no se pasan argumentos. Sin esta lista, los desajustes pueden no ser revelados, por lo que el compilador no puede generar mensajes de diagnóstico al respecto. Consulte Argumentos para obtener más información sobre la comprobación de tipos.
El ámbito del prototipo en el compilador de Microsoft C es ahora compatible con ANSI cuando se compila con la opción de compilador /Za. Esto significa que si declara una etiqueta struct
o union
dentro de un prototipo, la etiqueta se introduce en ese ámbito en lugar de en el ámbito global. Por ejemplo, cuando se compila con /Za para el cumplimiento de ANSI, nunca se puede llamar a esta función sin obtener un error de desajuste de tipo:
void func1( struct S * );
Para corregir su código, defina o declare la etiqueta struct
o union
en el ámbito global antes del prototipo de la función:
struct S;void func1( struct S * );
Con /Ze, la etiqueta se sigue introduciendo en el ámbito global.
Vea también
Funciones