Pregunta

¿Qué es útil sobre esta sintaxis C & # 8212; utilizando declaraciones de función de estilo 'K & amp; R'?

int func (p, p2)
    void* p;
    int  p2;
{
    return 0;
}

Pude escribir esto en Visual Studios 2010beta

// yes, the arguments are flipped
void f()
{
    void* v = 0;
    func(5, v);
}

No entiendo. ¿Cuál es el punto de esta sintaxis? Puedo escribir:

int func (p, p2)
    int  p2;
{
    return 0;
}
// and write
int func (p, p2)
{
    return 0;
}

Lo único que parece especificar es cuántos parámetros usa y el tipo de retorno. Supongo que los parámetros sin tipos son geniales, pero ¿por qué permitirlo y el int paranName después del declarador de función? Es raro.

¿También sigue siendo C estándar?

¿Fue útil?

Solución

La pregunta que hace es realmente dos preguntas, no una. La mayoría de las respuestas hasta ahora intentaron cubrir todo con una manta genérica "este es el estilo K & amp; R" responda, aunque en realidad solo una pequeña parte tiene algo que ver con lo que se conoce como estilo K & amp; R (a menos que vea todo el lenguaje C como " K & amp; estilo-R " de una forma u otra:)

La primera parte es la sintaxis extraña utilizada en la función definición

int func(p, p2)
void *p;
int  p2; /* <- optional in C89/90, but not in C99 */
{
  return 0;
}

Esta es en realidad una definición de función de estilo K & amp; R. Otra respuesta ha cubierto esto bastante bien. Y no hay mucho, en realidad. La sintaxis está en desuso, pero aún es totalmente compatible incluso en C99 (excepto por "no hay una regla int implícita" en C99, lo que significa que en C99 no puede omitir la declaración de p2 ).

La segunda parte tiene poco que ver con K & amp; R-style. Me refiero al hecho de que la función se puede llamar con " intercambiada " argumentos, es decir, no se realiza ninguna comprobación del tipo de parámetro en dicha llamada. Esto tiene muy poco que ver con la definición de estilo K & amp; R per se, pero tiene todo que ver con que su función no tenga un prototipo. Verás, en C cuando declaras una función como esta

int foo();

en realidad declara una función foo que toma un número no especificado de parámetros de tipo desconocido . Puedes llamarlo como

foo(2, 3);

y como

j = foo(p, -3, "hello world");

ans, etc. (se entiende la idea);

Solo la llamada con los argumentos adecuados funcionará " (lo que significa que los demás producen un comportamiento indefinido), pero depende totalmente de usted garantizar su corrección. No se requiere que el compilador diagnostique los incorrectos, incluso si de alguna manera conoce mágicamente los tipos de parámetros correctos y su número total.

En realidad, este comportamiento es una característica del lenguaje C. Una peligrosa, pero una característica, sin embargo. Te permite hacer algo como esto

void foo(int i);
void bar(char *a, double b);
void baz(void);

int main()
{
  void (*fn[])() = { foo, bar, baz };
  fn[0](5);
  fn[1]("abc", 1.0);
  fn[2]();
}

es decir mezclar diferentes tipos de funciones en un "polimórfico" matriz sin ningún tipo de conversión (sin embargo, aquí no se pueden usar tipos de funciones variables). Una vez más, los peligros inherentes de esta técnica son bastante obvios (no recuerdo haberlo usado alguna vez, pero puedo imaginar dónde puede ser útil), pero eso es C después de todo.

Finalmente, el bit que une la segunda parte de la respuesta con la primera. Cuando realiza una definición de función de estilo K & amp; R, no introduce un prototipo para la función. En cuanto al tipo de función, su definición de func declara func como

int func();

es decir ni los tipos ni el número total de parámetros están declarados. En tu publicación original, dices "... parece especificar cuántos parámetros usa ...". ¡Hablando formalmente, no lo hace! Después de su definición de dos parámetros K & amp; estilo R func todavía puede llamar a func como

func(1, 2, 3, 4, "Hi!");

y no habrá ninguna violación de restricción en él. (Normalmente, un compilador de calidad le dará una advertencia).

Además, un hecho que a veces se pasa por alto es que

int f()
{
  return 0;
}

también es una definición de función de estilo K & amp; R que no introduce un prototipo. Para que sea "moderno" tendrías que poner un void explícito en la lista de parámetros

int f(void)
{
  return 0;
}

Finalmente, contrario a la creencia popular, tanto las definiciones de funciones de estilo K & amp; R como las declaraciones de funciones no prototipadas son totalmente compatibles en C99. El primero ha quedado en desuso desde C89 / 90, si no recuerdo mal. C99 requiere que la función se declare antes del primer uso, pero no se requiere que la declaración sea un prototipo. Aparentemente, la confusión proviene de la confusión terminológica popular: muchas personas llaman a cualquier declaración de función '' prototipo '', mientras que de hecho '' declaración de función '' no es lo mismo que "prototipo".

Otros consejos

Esta es una sintaxis bastante antigua de K & amp; R C (anterior a ANSI / ISO C). Hoy en día, no debería usarlo más (como ya ha notado su mayor desventaja: el compilador no verificará los tipos de argumentos por usted). El tipo de argumento por defecto es int en su ejemplo.

En ese momento, se usaba esta sintaxis, a veces se encontraban funciones como

foo(p, q) 
{
    return q + p;
}

que en realidad era una definición válida, ya que los tipos de foo , p y q están predeterminados en int .

Esta es simplemente una sintaxis antigua, anterior a la "ANSI C" sintaxis con la que podría estar más familiarizado. Se llama " K & amp; RC " ;, típicamente.

Los compiladores lo admiten para que esté completo y para poder manejar bases de código antiguas, por supuesto.

Esta es la sintaxis original de K & amp; R antes de que C se estandarizara en 1989. C89 introdujo prototipos de funciones, tomados de C ++, y en desuso la sintaxis de K & amp; R. No hay ninguna razón para usarlo (y muchas razones para no hacerlo) en el nuevo código.

Esa es una reliquia de cuando C no tenía prototipos para las funciones. En aquel entonces, se suponía que las funciones devolvían int y se suponía que todos sus argumentos eran int . No se realizó ninguna comprobación en los parámetros de la función.

Es mucho mejor usar prototipos de funciones en el lenguaje C actual.
Y usted debe usarlos en C99 (C89 todavía acepta la sintaxis anterior).

Y C99 requiere que se declaren funciones (posiblemente sin un prototipo). Si está escribiendo una nueva función desde cero, debe proporcionar una declaración ... conviértalo también en un prototipo: no pierde nada y obtiene una comprobación adicional del compilador.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top