¿Por qué gcc permite que los argumentos pasen a una función definida para estar sin argumentos?




compiler-errors (3)

En C, una función declarada con una lista de parámetros vacía acepta un número arbitrario de argumentos al ser llamados, que están sujetos a las promociones aritméticas habituales. Es responsabilidad del que llama asegurarse de que los argumentos proporcionados sean apropiados para la definición de la función.

Para declarar una función tomando cero argumentos, debe escribir void foo(void); .

Esto es por razones históricas; originalmente, las funciones C no tenían prototipos, ya que C evolucionó de B , un lenguaje sin tipo. Cuando se agregaron prototipos, las declaraciones originales sin tipo se dejaron en el idioma para compatibilidad con versiones anteriores.

Para que gcc advierta sobre listas de parámetros vacías, use -Wstrict-prototypes :

Advertir si una función se declara o define sin especificar los tipos de argumentos. (Se permite una definición de función antigua sin una advertencia si está precedida por una declaración que especifica los tipos de argumentos).

No entiendo por qué compila este código?

#include <stdio.h>
void foo() {
    printf("Hello\n");
}

int main() {
    const char *str = "bar";
    foo(str);
    return 0;
}

gcc ni siquiera lanza una advertencia de que estoy pasando demasiados argumentos a foo (). ¿Es este comportamiento esperado?


Por razones heredadas, declarar una función con () para una lista de parámetros significa esencialmente "averiguar los parámetros cuando se llama a la función". Para especificar que una función no tiene parámetros, use (void) .

Editar: Siento que estoy acumulando reputación en este problema por ser viejo. Para que los niños sepan cómo era la programación, aquí está mi primer programa . (No C; muestra con qué tuvimos que trabajar antes de eso).


void foo() {
    printf("Hello\n");
}

foo(str);

en C, este código no infringe una restricción (lo haría si estuviera definido en su forma de prototipo con void foo(void) {/*...*/} ) y como no hay ninguna violación de restricción, el compilador no está requerido para emitir un diagnóstico.

Pero este programa tiene un comportamiento indefinido de acuerdo con las siguientes reglas de C:

De:

(C99, 6.9.1p7) "Si el declarador incluye una lista de tipos de parámetros, la lista también especifica los tipos de todos los parámetros, dicho declarador también sirve como un prototipo de función para llamadas posteriores a la misma función en la misma unidad de traducción. Si el declarante incluye una lista de identificadores, 142) los tipos de los parámetros se declararán en una lista de declaraciones siguiente. "

la función foo no proporciona un prototipo.

De:

(C99, 6.5.2.2p6) "Si la expresión que denota la función llamada tiene un tipo que no incluye un prototipo [...] Si el número de argumentos no es igual al número de parámetros, el comportamiento no está definido".

la llamada a la función foo(str) es un comportamiento indefinido.

C no exige que la implementación emita un diagnóstico para un programa que invoca un comportamiento indefinido, pero su programa sigue siendo un programa erróneo.





compiler-errors