2009-10-18 13 views

Respuesta

56

Esa es la sintaxis de estilo antiguo para las listas de parámetros, que aún se puede utilizar. En K & R C, también podría dejar fuera de las declaraciones de tipo y se definirían por defecto en int. es decir

main(argc, argv) 
char *argv[]; 
{ 
    return 0; 
} 

sería la misma función.

+13

Tanto C89/90 como C99 aún son oficialmente compatibles con las declaraciones de estilo de K & R. Sin embargo, en C99 todos los parámetros deben declararse explícitamente (ya no hay regla "implícita implícita"). – AnT

+1

Odio llegar tarde a la fiesta (¿como 4 años después?), Pero ¿quiere decir que en C99 deben declararse explícitamente * en la lista de parámetros * o * en la función *? Por ejemplo, la regla int predeterminada: dado que ya no se predetermina a int, entonces sus tipos deben declararse en la función antes del uso ** if ** los tipos no se suministraron en la lista de parámetros? –

+1

@ChrisCirefice Para responderle 4 años después: en C99, todos los parámetros deben declararse en la lista de parámetros. Las variables que se declaran en la función nunca han predeterminado a 'int', y por lo tanto deben declararse explícitamente. –

3

No hay diferencia, es solo que esa es la sintaxis anterior para las declaraciones de funciones en C - se usó antes de ANSI. Nunca escriba dicho código a menos que planee dárselo a sus amigos de los años 80. Además, nunca dependa de suposiciones de tipo implícito (como otra respuesta parece sugerir)

+0

Bien pre C99; se usó antes de ANSI, que se estandarizó en 1989 pero el proceso comenzó en 1983. –

+0

Gracias amigo. Se corrigió ahora ... – aviraldg

+1

Ejem ... Las declaraciones de estilo de K & R aún son oficialmente compatibles con C99, con solo un pequeño cambio, sin "int" implícito, todos los parámetros tienen que declararse explícitamente. – AnT

1

Es lo mismo, pero la moda antigua. Probablemente descubras que se trata de un código antiguo heredado.

4

Si bien la sintaxis anterior para la definición de la función aún funciona (con advertencias, si le pregunta a su compilador), su uso no proporciona prototipos de función.
Sin prototipos de función, el compilador no comprobará si las funciones se llaman correctamente.

#include <stdio.h> 
int foo(c) 
int c; 
{ return printf("%d\n", c); } 

int bar(x) 
double x; 
{ return printf("%f\n", x); } 

int main(void) 
{ 
    foo(42); /* ok */ 
    bar(42); /* oops ... 42 here is an `int`, but `bar()` "expects" a `double` */ 
    return 0; 
} 

Cuando se ejecuta el programa, la salida en mi máquina es

$ gcc proto.c 
$ gcc -Wstrict-prototypes proto.c 
proto.c:4: warning: function declaration isn’t a prototype 
proto.c:10: warning: function declaration isn’t a prototype 
$ ./a.out 
42 
0.000000 
10

Esto es lo que se llama K & R estilo o viejo estilo declaración.

Tenga en cuenta que esta declaración es significativamente diferente de la declaración moderna. K & La declaración R no introduce un prototipo para la función, lo que significa que no expone los tipos de los parámetros al código externo.

24

Lo que también es interesante es la diferencia de convención de llamadas con funciones y funciones sin prototipo. Considere una vieja definición de estilo:

void f(a) 
float a; { 
/* ... */ 
} 

En este caso, la convención de llamada es que todos los argumentos son promovidos antes de ser pasados ​​a la función. Entonces, si f recibe un double pero el parámetro tiene el tipo float (que es perfectamente válido) el compilador debe emitir un código que convierta el doble en un flotante antes de ejecutar el cuerpo de la función.

Si incluye un prototipo, el compilador ya no realiza más promociones automáticas y los datos pasados ​​se convierten a los tipos de los parámetros del prototipo como si fueran asignados.Así que lo siguiente no es legal y da como resultado un comportamiento indefinido:

void f(float a); 
void f(a) 
    float a; { 

} 

En este caso, la definición de la función sería convertir el parámetro enviado desde double (la forma promovido) a float porque la definición es de estilo antiguo. Pero el parámetro se envió como un flotante, porque la función tiene un prototipo. Sus opciones de resolver las contradicciones son los dos siguientes:

// option 1 
void f(double a); 
void f(a) 
    float a; { 

} 

// option 2 
// this declaration can be put in a header, but is redundant in this case, 
// since the definition exposes a prototype already if both appear in a 
// translation unit prior to the call. 
void f(float a); 

void f(float a) { 

} 

Opción 2 debe ser preferido si usted tiene la elección, ya que se deshace de la definición de estilo antiguo en la delantera. Si tales tipos de funciones contradictorias para una función aparecen en la misma unidad de traducción, el compilador generalmente le dirá (pero no es obligatorio). Si tales contradicciones aparecen en varias unidades de traducción, el error posiblemente pasará desapercibido y puede dar lugar a errores difíciles de predecir. Lo mejor es evitar estas definiciones de estilo antiguo.

Cuestiones relacionadas