Pregunta

Transcripción de la sesión:

>type lookma.c
int main() {
  printf("%s", "no stdio.h");
}

>cl lookma.c
Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 14.00.50727.762 for 80x86
Copyright (C) Microsoft Corporation.  All rights reserved.

lookma.c
Microsoft (R) Incremental Linker Version 8.00.50727.762
Copyright (C) Microsoft Corporation.  All rights reserved.

/out:lookma.exe
lookma.obj

>lookma
no stdio.h
¿Fue útil?

Solución

En el modo de cumplimiento estricto (eso significa "en teoría"), invoca un comportamiento indefinido (que es malo) cuando llama a una función que toma un número variable de argumentos sin una declaración prototipo de la función en el alcance. Eso significa que el compilador puede hacer lo que quiera con un programa que usa printf () sin el prototipo de #include < stdio.h > o una declaración equivalente . " Cualquier cosa que le guste " incluye trabajar correctamente como una de las opciones; esa parece ser la opción elegida por su ejemplo.

En la práctica, el código funcionará bien con la mayoría de los compiladores prácticos, incluso sin la declaración formal de la función printf () .

Como señaló qrdl, la función se encontró porque el compilador de C se vincula con la biblioteca de C.

Tenga en cuenta que el comentario de Chris Young sobre C99 y 'implícito int' es correcto, pero la regla sobre 'las funciones de argumentos variables deben tener un prototipo de alcance' se aplica tanto a C89 como a C99. La mayoría de los compiladores no funcionan en un modo estricto de compatibilidad C99 por defecto porque hay demasiado código que no se compilaría así.

Chris Young comentó:

  

Para aclarar, mi comentario fue sobre C99 eliminando declaraciones implícitas. Al decir "implícito int", creo que se está refiriendo a la característica C89 de permitir declaraciones como foo (void); significa int foo (void) ;, algo que C99 también eliminó.

Chris es, por supuesto, correcto. Se eliminaron dos características de 'declaración implícita' del estándar C99. El prólogo del estándar los enumera como:

  • eliminar int
  • implícito
  • eliminar declaración de función implícita

No estaba pensando (y por lo tanto no escribiendo) con suficiente claridad. Sin embargo, tanto C89 como C99 requieren un prototipo en alcance para funciones que toman un número variable de argumentos.

Para ilustrar:

extern int pqr();
int main(void)
{
    int i = pqr(1, 3);
    return i;
}

Sin la primera línea, este es un fragmento C89 correcto con una declaración implícita de la función pqr () como una función que devuelve un entero (con argumentos no especificados). Si la primera línea se reemplaza por extern pqr (); , entonces este es un fragmento C89 correcto con una declaración explícita de pqr () como una función que devuelve un entero ( con argumentos no especificados), pero el tipo de retorno es 'implícito int '. Tal como está escrita, la función se declara explícitamente y tiene un tipo de retorno int explícito, pero aún tiene argumentos no especificados. Creo que es válido C99, aunque no del todo deseable. Ciertamente, GCC (3.4.4) lo acepta con las opciones ' -std = c99 -pedantic " ;. Idealmente, la declaración de función debe incluir el prototipo completo. (Y, si pqr () se definiera con puntos suspensivos, ese prototipo sería requerido en teoría !)

Otros consejos

Originalmente había etiquetado este C ++, pero parece ser un programa en C. C proporcionará automáticamente una declaración implícita para una función si no hay un prototipo en el alcance (como por la omisión de #include < stdio.h >). La declaración implícita sería:

int printf();

Significa que printf es una función que devuelve un int y puede tomar cualquier número de argumentos. Este prototipo pasó a funcionar para su llamada. Debe #incluir < stdio.h >

Finalmente, debo agregar que el estándar C actual (ISO / IEC 9899: 1999 o coloquialmente " C99 ") no permite declaraciones implícitas, y este programa no se conformaría. Se eliminaron las declaraciones implícitas. Creo que su compilador no es compatible con C99. C ++ también requiere prototipos correctos y no hace declaraciones implícitas.

printf () se encuentra en la biblioteca C estándar y el enlazador siempre vincula la biblioteca estándar a su ejecutable, por lo que se encontrarán las funciones estándar y no habrá problemas de enlace.

Si no se incluyen los resultados de encabezado apropiados al usar una función que no fue prototipada, esto puede generar problemas, ya que el compilador de C asume que la función sin prototipo devuelve int y toma un número variable de argumentos. Así que siempre incluya encabezado: es su valla de seguridad.

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