2012-01-22 20 views
7

El estándar C establece que, para una definición de función, si el declarador incluye una lista de identificadores, los tipos de los parámetros se declararán en una lista de declaraciones siguiente. Aparentemente, esto hace la diferencia.Declaración de parámetros fuera del declarador

extern int max(int a, int b) 
{ 
return a > b ? a : b; 
} 

extern int max(a, b) 
int a, b; 
{ 
return a > b ? a : b; 
} 

Aquí int a, b; es la lista de declaraciones para los parámetros. La diferencia entre estas dos definiciones es que la primera forma actúa como como una declaración de prototipo que fuerza la conversión de los argumentos de llamadas subsiguientes a la función, mientras que la segunda forma no.

¿Qué significa esto para el programador y afecta el código que produce el compilador?

Respuesta

11

Significa que en el segundo caso, es responsabilidad de la persona que llama asegurarse de que los argumentos proporcionados sean del tipo correcto; no se proporcionará ninguna conversión implícita (aparte de las promociones de argumento predeterminadas). Desde la sección 6.5.2.2:

Si la expresión que denota la función de llamada tiene un tipo que no incluye un prototipo , las promociones enteros se llevan a cabo en cada argumento.

...

Si la expresión que denota la función de llamada tiene un tipo que sí incluye un prototipo, los argumentos se convierten implícitamente, como por asignación, a los tipos de los parámetros correspondientes .

Así código de llamada como esto va a estar bien:

char x = 3; 
char y = 7; 
max(x, y); // Equivalent to max((int)x, (int)y) 

porque x y y son promovidos a int antes de ser colocado en la pila.

Sin embargo, un código como éste no va a estar bien:

double x = 3.0; 
long y = 7; 
max(x, y); // Uh-oh 

x y y se colocará en la pila como double y long, pero max() intentará leer dos int s, lo que resultará en indefinido comportamiento (en la práctica, los bits en bruto serán reinterpretados).

Esta es una razón para no usar el segundo formulario; la única razón por la que está en el estándar es para proporcionar compatibilidad con el código (extremadamente) heredado. Si está utilizando GCC, puede aplicar esto utilizando el indicador -Wold-style-definition; Espero que otros compiladores ofrezcan algo equivalente.

Cuestiones relacionadas