В C основной не обязательно должна быть функция?

Этот код компилируется, но без сюрпризов он терпит неудачу при связывании (нет основного найденного):

Листинг 1:

void main(); 

Ошибка связи: \ mingw \ lib \ libmingw32.a (main.o): main.c :(. Текст + 0x106) неопределенная ссылка на _WinMain @ 16 ‘

Но код ниже компилируется и ссылки отлично, с предупреждением:

Листинг 2:

 void (*main)(); 

предупреждение: «main» обычно является функцией

Вопросы:

  1. В листинге 1 линкер должен был пожаловаться на отсутствие «основного». Почему он ищет _WinMain @ 16?

  2. Исполняемый файл, созданный в листинге 2, просто сбой. Какова причина?

Спасибо за ваше время.

Случай 1. является специфичным для Windows – компилятор, вероятно, генерирует символ _WinMain когда main правильно определен.

Случай 2. – у вас есть указатель, но как статическая переменная, он инициализирован до нуля , таким образом, сбой.

Правда, main не должно быть функцией. Это было использовано в некоторых запутанных программах, которые содержат двоичный программный код в массиве main .

Возвращаемый тип main () должен быть int (не void ). Если компоновщик ищет WinMain , он считает, что у вас есть приложение GUI.

В большинстве систем компиляции C отсутствует информация о типе, связанная с связанными символами. Вы можете объявить основные, например:

 char main[10]; 

и линкер был бы совершенно счастлив. Как вы заметили, программа, скорее всего, сработает, и вы сможете искусно инициализировать содержимое массива.

Ваш первый пример не определяет main, он просто объявляет его, следовательно, ошибку компоновщика.

Второй пример определяет основной, но неправильно.

На платформах Windows основное устройство программы – WinMain, если вы не устанавливаете программу в качестве консольного приложения. «@ 16» означает, что он ожидает 16 байтов параметров. Таким образом, компоновщик будет очень доволен вами, если вы дадите ему функцию WinMain с 16 байтами параметров.

Если вы хотите консольное приложение, это ваше указание, что вы что-то испортили.

Вы объявили указатель на функцию с именем main, и компоновщик предупредил вас, что это не сработает.

Сообщение _WinMain связано с тем, как работают программы Windows. Ниже уровня выполнения C исполняемый файл Windows имеет WinMain.

Попробуйте переопределить его как int main(int argc, char *argv[])

У вас есть ошибка компоновщика. Компилятор рассчитывает найти функцию с этой «сигнатурой» – не пустое без параметров

См. http://publications.gbdirect.co.uk/c_book/chapter10/arguments_to_main.html и т. Д.

В листинге 1 вы говорите: «Есть основной (), определенный в другом месте моего кода — я обещаю!». Вот почему он компилируется. Но вы лежите там, поэтому связь не удалась. Причина, по которой вы получаете недостающую ошибку WinMain16, заключается в том, что стандартные библиотеки (для компилятора Microsoft) содержат определение для main (), которое вызывает WinMain (). В программе Win32 вы должны определить WinMain (), и компоновщик будет использовать библиотечную версию main () для вызова WinMain ().

В листинге 2 у вас есть символ с именем main defined, поэтому и компилятор, и компоновщик счастливы, но код запуска будет пытаться вызвать функцию, находящуюся в местоположении «main», и обнаружить, что там действительно нет функции, и авария.

1.) Зависимая функция (компилятор / платформа) вызывается перед выполнением кода в main и, следовательно, с вашим поведением ( _init в случае linux / glibc).
2) Ошибка кода во втором случае оправдана, так как система не может получить доступ к содержимому main функции символа как функции, которая фактически является указателем на функцию, указывающим на произвольное местоположение.