Ответ 1
Случай 1. зависит от Windows - компилятор, вероятно, генерирует символ _WinMain
, когда main
правильно определен.
Случай 2. - у вас есть указатель, но как статическая переменная , она инициализируется нулем, таким образом, сбой.
Этот код компилируется, но без сюрпризов он терпит неудачу при связывании (нет основного найденного):
Листинг 1:
void main();
Ошибка связи:\mingw\lib\libmingw32.a(main.o): main.c:(. текст + 0x106) undefined ссылка на _WinMain @16 '
Но код ниже компилируется и ссылки отлично, с предупреждением:
Листинг 2:
void (*main)();
предупреждение: "main" обычно является функцией
Вопросы:
В листинге 1, линкер должен иметь жаловался на отсутствие "основного". Зачем он ищет _WinMain @16?
Исполняемый файл листинг 2 просто сбой. Что причина?
Спасибо за ваше время.
Случай 1. зависит от Windows - компилятор, вероятно, генерирует символ _WinMain
, когда main
правильно определен.
Случай 2. - у вас есть указатель, но как статическая переменная , она инициализируется нулем, таким образом, сбой.
Правда, main
не обязательно должна быть функцией. Это было использовано в некоторых запутанных программах, которые содержат двоичный программный код в массиве с именем main
.
Возвращаемый тип main() должен быть int
(не void
). Если компоновщик ищет WinMain
, он считает, что у вас есть приложение с графическим интерфейсом.
В большинстве систем компиляции 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 вы говорите: "Там main() определен в другом месте моего кода --- я обещаю!". Вот почему он компилируется. Но вы лежите там, поэтому связь не удалась. Причина, по которой вы получаете недостающую ошибку WinMain16, заключается в том, что стандартные библиотеки (для компилятора Microsoft) содержат определение для main(), которое вызывает WinMain(). В программе Win32 вы должны определить WinMain(), и компоновщик будет использовать библиотечную версию main() для вызова WinMain().
В листинге 2 у вас есть символ с именем main defined, поэтому и компилятор, и компоновщик счастливы, но код запуска будет пытаться вызвать функцию, которая находится в местоположении "main", и обнаружить, что на самом деле нет функции там и сбой.
1.) Зависимая функция (компилятор/платформа) вызывается перед выполнением кода в main и, следовательно, вашего поведения (_init
в случае linux/glibc).
2) Ошибка кода во втором случае оправдана, так как система не может получить доступ к содержимому символа main
как функции, которая на самом деле является указателем функции, указывающим на произвольное местоположение.