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

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

Листинг 1:

void main();

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

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

Листинг 2:

void (*main)();

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

Вопросы:

  • В листинге 1, линкер должен иметь жаловался на отсутствие "основного". Зачем он ищет _WinMain @16?

  • Исполняемый файл листинг 2 просто сбой. Что причина?

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

Ответ 1

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

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

Ответ 2

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

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

Ответ 3

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

char main[10];

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

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

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

Ответ 4

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

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

Ответ 5

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

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

Ответ 6

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

У вас есть ошибка компоновщика. Линкер рассчитывает найти функцию с этой "сигнатурой" - не пустое без параметров

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

Ответ 7

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

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

Ответ 8

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