2010-06-22 12 views
34

¿Cuáles son las diferencias entre una declaración de función R K & y una declaración de función ANSI?Declaración de función: K & R frente a ANSI

+1

¿Puedes dar un ejemplo de cada estilo? –

+2

Una pregunta relacionada: http://stackoverflow.com/questions/1630631/what-is-useful-about-this-c-syntax – sharptooth

+1

Es "K & R", no "knr" (He solucionado la pregunta por usted) , que significa Kernighan y Ritchie, y típicamente se refiere a la sintaxis C descrita en su libro seminal sobre C, circa 1978, * The C Programming Language *. Este artículo puede ser útil para usted: http://en.wikipedia.org/wiki/C_(programming_language)#K.26R_C –

Respuesta

54

K & La sintaxis R es obsoleta, puede omitirla a menos que tenga que mantener un código muy antiguo.

// K&R syntax 
int foo(a, p) 
    int a; 
    char *p; 
{ 
    return 0; 
} 

// ANSI syntax 
int foo(int a, char *p) 
{ 
    return 0; 
} 
+13

El uso de la sintaxis de K & R con el tipo 'void *' es un anacronismo, ya que K & R C no * tener * 'void *'. – caf

+3

@caf No, estaba usando una extensión no estándar para el idioma :-) – Wizard

+3

En realidad, esta es una definición de función K & R, no una declaración de función K & R. –

19

Declaraciones/Definiciones &-Estilo R legado K

Cuando Kernighan y Ritchie publicaron por primera vez "El Lenguaje de Programación C", C todavía no ofrecen prototipos de funciones completas. Existían declaraciones de funciones hacia adelante, pero con el único propósito de indicar un tipo de devolución. Para las funciones que devolvieron int, no fueron necesarias hasta C99.

Por C89, se ha agregado la noción de un prototipo de función, que también especifica los tipos de los parámetros (e, implícitamente, su número). Dado que un prototipo es también un tipo de declaración de función, el término no oficial "K & declaración de función R" se utiliza a veces para una declaración de función que no es también un prototipo.

// K&R declarations, we don't know whether these functions have parameters. 
int foo(); // this declaration not strictly necessary until C99, because it returns int 
float bar(); 

// Full prototypes, specifying the number and types of parameters 
int foo(int); 
float bar(int, float); 

// K&R definition of a function 
int foo(a) 
    int a; // parameter types were declared separately 
{ 
    // ... 
    return 0; 
} 

// Modern definition of a function 
float bar(int a, float b) 
{ 
    // ... 
    return 0.0; 
} 

El accidental K & Declaración R

Vale la pena señalar que los recién llegados a C pueden utilizar accidentalmente K & declaraciones R cuando tienen la intención de utilizar un prototipo completo, debido a que no se dan cuenta de que un vacío la lista de parámetros debe especificarse como void.

Si se declara y define una función como

// Accidental K&R declaration 
int baz(); // May be called with any possible set of parameters 

// Definition 
int baz() // No actual parameters means undefined behavior if called with parameters. 
      // Missing "void" in the parameter list of a definition is undesirable but not 
      // strictly an error, no parameters in a definition does mean no parameters; 
      // still, it's better to be in the habit of consistently using "void" for empty 
      // parameter lists in C, so we don't forget when writing prototypes. 
{ 
    // ... 
    return 0; 
} 

... entonces no lo ha hecho dado un prototipo de una función que no toma ningún parámetro, sino una declaración de K & R-estilo para una función que acepta un número desconocido de parámetros de tipo desconocido.

notas de hormigas en this answer a una pregunta similar que esta sintaxis está obsoleta, pero todavía es legal a partir del C99 (y que la función punteros a funciones con número desconocido y tipo de parámetros todavía tienen aplicaciones potenciales, aunque con alto riesgo de comportamiento no definido) ; como tal, los compiladores compatibles, en el mejor de los casos, producirán una advertencia si se declara o se llama a una función sin un prototipo adecuado.

Llamar a las funciones sin prototipos es menos seguro, porque el compilador no puede verificar que haya pasado el número correcto y los tipos de parámetros en el orden correcto; comportamiento indefinido si la llamada no es realmente correcta.

La forma correcta de declarar y definir una función sin parámetros es, por supuesto:

// Modern declaration of a parameterless function. 
int qux(void); // "void" as a parameter type means there are no parameters. 
       // Without using "void", this would be a K&R declaration. 

// Modern definition of a parameterless function 
int qux(void) 
{ 
    // ... 
    return 0; 
} 
+1

Debe aclarar qué quiere decir con 'versiones anteriores de C'. Usted dice: _Las versiones anteriores del lenguaje C no requerían prototipos de función completa, pero aún requerían una declaración de una función antes de que pudiera llamarse. Sin embargo, las versiones anteriores de C, es decir, C pre-estándar, no tenían prototipos en absoluto y no requirió la declaración directa de una función antes de que pudiera llamarse. Incluso C89/C90 no requirió tales declaraciones directas. Era C99 que requería declaraciones de funciones (pero aún no ordenaba prototipos) antes de su uso. –

+0

@JonathanLeffler Gracias por los consejos, he leído un poco más (principalmente el artículo de Wikipedia sobre K & R era C) y lo limpié, creo que debería ser históricamente preciso ahora. –

0

sólo quiero añadir que en los tradicionales K & Modificadores de tipo de estilo R para funciones que devuelven un valor int aren' t incluso necesario.

en cuenta la moderna notación C11 de un sencillo programa HelloWorld:

int main(int argc, char **argv) { 
    printf("hello world\n"); 
    return 0; 
} 

Esto es equivalente a la & R estilo de notación K:

main(argc, argv) 
int argc; 
char **argv; 
{ 
printf("hello world\n"); 
return 0; 
} 

Tenga en cuenta que la int antes main() se ignora, pero el código aún se compila. Eso es parte de la definición de K & R.

Cita Wikipedia:

En las primeras versiones de C, únicas funciones que devuelven un valor no int necesitaba ser declarada si se usa antes de la definición de función; se asumió que una función utilizada sin ninguna declaración previa devuelve el tipo int, si se usó su valor.

--source: https://en.wikipedia.org/wiki/C_(programming_language)#K.26R_C

Este es sin duda un legado de estilo de codificación y debe evitarse debido a problemas en la transparencia, pero muy a menudo viejos libros de texto algoritmo favorece este tipo de K & estilo R.

+2

Y para el masoquista, podría tener 'main (argc, argv) char ** argv; {...} 'ya que el tipo de argumentos sin una especificación de tipo explícita era, por inferencia,' int'. Además, 'función (a, b, c, d) char * d, doble c, a; {...} 'también estaba bien; los nombres no tenían que aparecer en la lista en la sección de tipo en el orden en que aparecen en la lista de argumentos. –

Cuestiones relacionadas