Prototipos de función

Una declaración de función precede a la definición de función y especifica el nombre, el tipo devuelto, la 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

declaration:
declaration-specifiersattribute-seqoptinit-declarator-listopt;

/* attribute-seqopt es específico de Microsoft */

declaration-specifiers:
storage-class-specifierdeclaration-specifiersopt
type-specifierdeclaration-specifiersopt
type-qualifierdeclaration-specifiersopt

init-declarator-list:
init-declarator
init-declarator-list , init-declarator

init-declarator:
declarator
declarator = initializer

declarator:
pointeroptdirect-declarator

direct-declarator: /* Un declarador de función */
direct-declarator(parameter-type-list) /* Declarador de estilo nuevo */
direct-declarator(identifier-listopt) /* Declarador de estilo obsoleto */

El prototipo tiene la misma forma que la definición de función, excepto que termina con un punto y coma inmediatamente después del paréntesis de cierre y, por consiguiente, no tiene ningún cuerpo. En cualquier caso, el tipo de valor devuelto debe coincidir con el tipo de valor devuelto especificado en la definición de función.

Los prototipos de función tienen los siguientes usos importantes:

  • Establecen el tipo de valor devuelto para funciones que devuelven tipos diferentes de int. Aunque las funciones que devuelven valores int no requieren prototipos, estos se recomiendan.

  • Sin prototipos completos se realizan conversiones estándar, pero no se hace ningún intento de 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 se definan esas funciones.

  • La lista de parámetros se utiliza para comprobar que los argumentos de la llamada de función coinciden con los parámetros de la definición de función.

El tipo convertido de cada parámetro determina la interpretación de los argumentos que la llamada de función coloca en la pila. Un error de coincidencia de tipos entre un argumento y un parámetro puede provocar que los argumentos de la pila no se interpreten correctamente. Por ejemplo, en un equipo de 16 bits, si se pasa un puntero de 16 bits como argumento y, después, se declara como un parámetro long , los primeros 32 bits de la pila se interpretan como un parámetro long . Este error crea problemas no solo con el parámetro long, sino con todos los parámetros posteriores. 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. Después se pueden comprobar las llamadas de función que preceden a la definición de función (o que se producen en otros archivos de código fuente) para comprobar si hay discrepancias entre argument-type y return-type. 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 función.

Las declaraciones de parámetro completas (int a) se pueden mezclar con declaradores abstractos (int) en la misma declaración. Por ejemplo, la siguiente declaración es válida:

int add( int a, int );

El prototipo puede incluir tanto el tipo como el identificador de cada expresión que se pasa como argumento. Pero tales identificadores solo están en ámbito 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 pasa ningún argumento. Sin esta lista es posible que las discordancias no se revelen, así que el compilador no puede generar mensajes de diagnóstico relacionados con ellos. Para obtener más información sobre la comprobación de tipos, vea Argumentos.

El ámbito de prototipo en el compilador de Microsoft C es ahora compatible con ANSI cuando se compila con la opción del compilador /Za . 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, al compilar con /Za para la conformidad con ANSI, nunca se puede llamar a esta función sin obtener un error de coincidencia de tipos:

void func1( struct S * );

Para corregir el código, defina o declare struct o union en el ámbito global antes del prototipo de función:

struct S;
void func1( struct S * );

Bajo /Ze, la etiqueta continúa introduciéndose en el ámbito global.

Vea también

Funciones