2010-02-12 10 views
11

Este código se compila, pero no hay sorpresas, se produce un error durante el enlazado (sin principales que se encuentran):En C, principal no necesita ser una función?

Listado 1:

void main(); 

Error de enlace: \ MinGW \ lib \ libmingw32.a (principal. o):. main.c :(texto + 0x106) referencia indefinida a _WinMain @ 16'

embargo, el código de abajo compila y enlaza muy bien, con una advertencia:

Listado 2:

void (*main)(); 

advertencia: 'principal' es por lo general una función

Preguntas:

  1. en el Listado 1, enlazador debe tener se quejaron de falta "principal". ¿Por qué está buscando _WinMain @ 16?

  2. El ejecutable generado a partir de lista 2 simplemente se bloquea. ¿Cuál es el motivo?

Gracias por su tiempo.

+1

Se bloquea porque la desfiltración 'void (* main)();' ejecuta un puntero NULL (si ese es su código completo) – Mawg

Respuesta

4

Caso 1. Es específico de Windows: el compilador genera probablemente el símbolo _WinMain cuando main está definido correctamente.

Caso 2. - que tiene un puntero, pero variable estática como se inicializa a cero, por lo tanto el accidente.

+1

El compilador generalmente requiere '_WinMain' cuando desarrolla aplicaciones para Windows. Muchos compiladores tienen una plantilla * de consola *, que requiere '' principal '', pero no proporciona todas las ventajas de las ventanas, simplemente es anticuado C. –

+0

Thomas, gracias, eso sí sé. Simplemente no estaba seguro si VS podría "implantar" _WinMain automáticamente en programas de consola. –

1

Intenta redefinir como int main(int argc, char *argv[])

Lo que tenemos es un error de vinculador. El enlazador espera encontrar una función con la "firma" - no anula sin parámetros

Ver http://publications.gbdirect.co.uk/c_book/chapter10/arguments_to_main.html etc

+3

La función main no necesita tener argumentos. int main (void) también es una firma perfectamente válida. Sin embargo, en C (a diferencia de C++) int main() significa que puede tomar cualquier argumento, lo cual es un mal estilo, pero AFAIK sigue siendo legal. – Tronic

+0

De acuerdo (lo siento) Consulte http://en.wikipedia.org/wiki/Main_function_%28programming%29#C_and_C.2B.2B Pero, en cualquier caso, obviamente tiene un error de enlazador porque no se declara ninguna función principal (¿convenido?). Algunos entornos (especialmente aquellos para desarrollar programas basados ​​en GUI) proporcionarán esto automágicamente. – Mawg

28

Es cierto, main no tiene por qué ser una función. Esto se ha explotado en algunos programas ofuscados que contienen código de programa binario en una matriz llamada main.

El tipo de retorno de main() debe ser int (no void). Si el enlazador está buscando WinMain, cree que tiene una aplicación GUI.

+14

http://www.ioccc.org/years.html#1984_mullender –

+0

+1, no sabía que :) –

6

En la mayoría de los sistemas de compilación C, no hay información de tipo asociada con símbolos vinculados. Puede declarar main como e.g .:

char main[10]; 

y el enlazador sería perfectamente feliz. Como notó, el programa probablemente se bloquee, a menos que inicialice hábilmente el contenido de la matriz.

Su primer ejemplo no define main, simplemente lo declara, de ahí el error del enlazador.

El segundo ejemplo define main, pero incorrectamente.

+0

> El segundo ejemplo define main, pero incorrectamente. ¿Esto significa que el compilador asigna algo de almacenamiento para este código? 'void (* main)();' ¿Esto no es solo una declaración, puntos principales de una función que toma un número no especificado de argumentos y no devuelve nada? (a diferencia de una definición)? – Gowtham

+1

+1 para la publicación. ¿Puedes dar un ejemplo de principal declarado como una matriz y el código funcionará? Tengo mucha curiosidad por saber esto. Nunca he encontrado un código así. – Jay

+1

En los viejos tiempos, era más fácil hacer cosas como esa. Para ver un ejemplo de una matriz ejecutable, consulte http://stackoverflow.com/questions/2251859/cant-find-my-syntax-error-vc-says-theres-one/2251892#2251892 –

2

Usted declaró una función de puntero a función principal, y el vinculador le advirtió que esto no funcionaría.

El mensaje _WinMain tiene que ver con cómo funcionan los programas de Windows. Debajo del nivel del tiempo de ejecución de C, un ejecutable de Windows tiene un WinMain.

0

En el listado 1, dices "Hay un main() definido en otra parte de mi código --- ¡lo prometo!". Por eso compila. Pero estás mintiendo allí, por lo que el enlace falla. La razón por la que obtiene el error WinMain16 que falta, es porque las bibliotecas estándar (para el compilador de Microsoft) contienen una definición para main(), que llama a WinMain(). En un programa Win32, definiría WinMain() y el enlazador utilizaría la versión de biblioteca de main() para llamar a WinMain().

En el Listado 2, tiene un símbolo llamado main defined, por lo tanto el compilador & el enlazador está contento, pero el código de inicio intentará llamar a la función que está en la ubicación "main" y descubrirá que realmente no hay un funcionar allí, y chocar.

+0

¿Significa esto que el compilador asigna algo de almacenamiento para este código? 'void (* main)();' ¿Esto no es solo una declaración, puntos principales de una función que toma una cantidad no especificada de argumentos y no devuelve nada? (a diferencia de una definición)? – Gowtham

+0

No. asigna espacio para un * puntero * a una función que toma un número no especificado de argumentos y no devuelve nada. 'char * main;' o incluso 'void * main;' hubiera logrado lo mismo. –

0

1.) Se llama a una función dependiente (compilador/plataforma) antes de que se ejecute el código en main y de ahí su comportamiento (_init en el caso de linux/glibc).
2) El bloqueo del código en el segundo caso se justifica porque el sistema no puede acceder al contenido del símbolo main como una función que en realidad es un puntero de función que apunta a una ubicación arbitraria.

3

En plataformas Windows, la unidad principal del programa es WinMain si no configura el programa como una aplicación de consola. El "@ 16" significa que está esperando 16 bytes de parámetros. Entonces el enlazador estaría muy contento con usted siempre que le dé una función llamada WinMain con 16 bytes de parámetros.

Si quería una aplicación de consola, esta es su indicación de que ha estropeado algo.

Cuestiones relacionadas