c++ main forward-declaration function-declaration

¿Int main() necesita una declaración en C++?



forward-declaration function-declaration (7)

Me enseñaron que las funciones necesitan declaraciones para ser llamadas.

En efecto. Una función debe ser declarada antes de que pueda ser llamada.

¿Por qué no añadimos una declaración para la función main ?

Bueno, no llamaste a la función main . De hecho, no debe llamar a main en absoluto 1 , por lo que nunca es necesario declarar main antes de nada.

Sin embargo, técnicamente, todas las definiciones también son declaraciones, por lo que su definición de main también se declara main .

Nota al pie 1: El estándar de C ++ dice que es un comportamiento indefinido para llamar a main desde dentro del programa.

Esto permite que las implementaciones de C ++ coloquen un código de inicio especial de ejecución única en la parte superior de la página principal, si no pueden ejecutarlo antes desde los ganchos en el código de inicio que normalmente se llama main . De hecho, algunas implementaciones reales hacen esto, por ejemplo, llamando a una función de matemáticas rápidas que establece algunas marcas de FPU como denormals-are-zero.

En una implementación hipotética, la llamada principal podría resultar en cosas divertidas como volver a ejecutar constructores para todas las variables estáticas, reiniciar las estructuras de datos utilizadas por new / delete para realizar un seguimiento de las asignaciones u otra rotura total de su programa. O podría no causar ningún problema en absoluto. El comportamiento indefinido no significa que tenga que fallar en cada implementación.

Al leer acerca de las funciones en C ++, me enseñaron que las funciones necesitan declaraciones para ser llamadas. Por ejemplo:

#include <iostream> int main() { std::cout << "The result is " << sum(1, 2); return 0; } int sum(int x, int y) { return x + y; }

Devuelve un error, ya que no hay ninguna declaración para la sum la función.

main.cpp:4:36: error: use of undeclared identifier ''sum'' std::cout << "The result is " << sum(1, 2); ^ 1 error generated.

Para arreglar esto, agregaría la declaración:

#include <iostream> int sum(int x, int y); // declaration int main() { std::cout << "The result is " << sum(1, 2); return 0; } int sum(int x, int y) { return x + y; }

Mi pregunta es, ¿por qué no agregamos una declaración para la función main , como tendríamos que agregar para otras funciones, como la sum ?


Es ilegal llamar a main desde dentro de su programa. Eso significa que lo único que lo llamará es el tiempo de ejecución y el compilador / enlazador puede manejar la configuración. Esto significa que no necesita un prototipo para main .


No No puedes llamarlo de todos modos.

Solo necesita declaraciones de reenvío para las funciones llamadas antes de que se definan. Necesita declaraciones externas (que se parecen exactamente a las declaraciones a futuro) para funciones definidas en otros archivos.

Pero no puedes llamar a main en C ++, así que no necesitas uno. Esto se debe a que el compilador de C ++ puede modificar main para realizar la inicialización global.

[Miré crt0.c y tiene una declaración para main, pero eso no es ni aquí ni allá].


Se requiere el prototipo si desea llamar a la función, pero aún no está disponible, como la sum en su caso.

No debe llamarse main , por lo que no es necesario tener un prototipo. Incluso es una mala idea escribir un prototipo.


Una definición de una función es también una declaración de una función.

El propósito de declarar una función es dar a conocer al compilador. Declarar una función sin definirla permite utilizarla en lugares donde no es conveniente definirla. Por ejemplo:

  • Si se usa una función en un archivo fuente (A) diferente al que está definido en (B), debemos declararlo en A (generalmente a través de un encabezado que A incluye, como Bh ).
  • Si dos o más funciones pueden llamarse entre sí, entonces no podemos definir todas esas funciones antes que las otras, una de ellas debe ser la primera. Por lo tanto, las declaraciones se pueden proporcionar primero, y luego las definiciones.
  • Muchas personas prefieren colocar las rutinas de "nivel superior" antes en un archivo de origen y las subrutinas más tarde. Dado que esas rutinas de "nivel superior" llaman a varias subrutinas, las subrutinas deben declararse antes.

En C ++, un programa de usuario nunca llama main , por lo que nunca necesita una declaración antes de la definición. (Tenga en cuenta que podría proporcionar uno si lo desea. No hay nada especial acerca de una declaración de main a este respecto). En C, un programa puede llamar main . En ese caso, requiere que una declaración sea visible antes de la llamada.

Tenga en cuenta que main debe ser conocido por el código que lo llama. Este es un código especial en lo que normalmente se llama el código de inicio de tiempo de ejecución de C ++. El enlazador incluye ese código automáticamente cuando vincula un programa de C ++ con las opciones de vinculador adecuadas. Cualquiera que sea el idioma en el que está escrito el código, tiene la declaración de main que necesita para llamarlo correctamente.


Una definición de una función también la declara implícitamente. Si necesita hacer referencia a una función antes de que esté definida, debe declararla antes de usarla.

Así que escribir lo siguiente también es válido:

int sum(int x, int y) { return x + y; } int main() { std::cout << "The result is " << sum(1, 2); return 0; }

Si utiliza una declaración en un archivo para que el compilador conozca una función antes de que se defina, entonces su definición debe conocerse en el momento de la vinculación:

main.cpp

int sum(int x, int y); int main() { std::cout << "The result is " << sum(1, 2); return 0; }

sum.cpp

int sum(int x, int y) { return x + y; }

O la sum podría tener su origen en una biblioteca, por lo que ni siquiera la compilas tú mismo.

La función main no se usa / hace referencia en su código en ningún lugar, por lo que no es necesario agregar la declaración de main ningún lugar.

Antes y después de su función main , la biblioteca c ++ podría ejecutar algunos pasos de inicio y limpieza, y llamará a su función main . Si esa parte de la biblioteca se representara como código c ++, entonces contendría una declaración de int main() para que pueda compilarse. Ese código podría verse así:

int main(); int __main() { __startup_runtime(); main(); __cleanup_runtime(); }

Pero luego vuelve a tener el mismo problema con __main así que en algún momento ya no hay c ++ y una función determinada ( main ) solo representa el punto de entrada de su código.


No, el compilador no necesita una declaración de reenvío para main() .

main() es una función especial en C ++.

Algunas cosas importantes para recordar acerca de main () son:

  1. El enlazador requiere que exista una y solo una función main() al crear un programa ejecutable.
  2. El compilador espera una función main () en una de las dos formas siguientes:

int main () { /* body */ } int main (int argc, char *argv[]) { /* body */ }

donde el body es cero o más declaraciones

Una forma adicional aceptable es específica de la implementación y proporciona una lista de las variables de entorno en el momento en que se llama a la función:

int main (int argc, char* argv[], char *envp[]) { /* body */ }

El codificador debe proporcionar la "definición" de main usando una de estas formas aceptables, pero el codificador no necesita proporcionar una declaración. La definición codificada es aceptada por el compilador como la declaración de main ().

  1. Si no se proporciona una declaración de devolución, el compilador proporcionará una return 0; Como la última afirmación en el cuerpo de la función.

Además, a veces hay confusión sobre si un programa de C ++ puede hacer una llamada a main (). Esto no es recomendable. El borrador de C ++ 17 establece que main () "no debe usarse dentro de un programa". En otras palabras, no se puede llamar desde un programa. Véase, por ejemplo, el borrador de la Norma de trabajo para el lenguaje de programación C ++, con fecha "2017-03-21", Párrafo 6.6.1.3, página 66 . Me doy cuenta de que algunos compiladores admiten esto (incluido el mío), pero la próxima versión del compilador podría modificar o eliminar ese comportamiento, ya que el estándar usa el término "no debería".