Всегда ли выполнение программы начинается с main в C?

Должно ли выполнение программы начинаться с основного или можно изменить начальный адрес?

#include <stdio.h>

void fun();

#pragma startup fun

int main()
{
    printf("in main");
    return 0;
}

void fun()
{
    printf("in fun");
}

Эта программа печатает in fun перед in main.


person desprado    schedule 01.08.2011    source источник
comment
возможный дубликат Как вы используете препроцессор запуска pragma?   -  person Mat    schedule 01.08.2011


Ответы (3)


В стандарте ANSI указано, что команда '#pragma' имеет произвольный эффект, определяемый реализацией. В препроцессоре GNU C '#pragma' сначала пытается запустить игру 'мошеннически'; если это не удается, он пытается запустить игру «взломать»; если это не удается, он пытается запустить GNU Emacs, отображающий Ханойскую башню; если это не удается, он сообщает о фатальной ошибке. В любом случае предварительная обработка не продолжается.

— Ричард М. Столмен, Препроцессор GNU C, версия 1.34

Выполнение программы начинается с кода запуска или «времени выполнения». Обычно это какая-то процедура на ассемблере, называемая _start или что-то в этом роде, расположенная (на машинах Unix) в файле crt0.o, который поставляется с пакетом компилятора. Он выполняет настройку, необходимую для запуска исполняемого файла C (например, настройку stdin, stdout и stderr, векторов, используемых atexit()... для C++, он также включает инициализацию глобальных объектов, т.е. запуск их конструкторов). Только после этого управление переходит к main().

Как красноречиво говорит цитата в начале моего ответа, то, что делает #pragma, полностью зависит от вашего компилятора. Проверьте его документацию. (Я предполагаю, что ваш pragma startup, который, кстати, должен начинаться с #, указывает среде выполнения сначала вызывать fun()...)

person DevSolar    schedule 01.08.2011
comment
На самом деле я бы хотел, чтобы разработчики компиляторов придерживались позиции Столлмана. Это спасло бы нас от таких глупостей, как pragma once или предупреждения компилятора, жестко отключающие исходный код... - person DevSolar; 01.08.2011

Программы C не обязательно начинаются с main() функции. Некоторые коды выполняются до main(), которые обнуляют все неинициализированные глобальные переменные и инициализируют другие глобальные переменные правильным значением. Например, рассмотрим следующий код:

int a;
int b = 10;

int main()
{
    int c = a * b;
    return 0;
}

В приведенном выше примере кода a и b назначаются 0 и 10 соответственно перед выполнением первой строки в main().

Директива #pragma предназначена для определения поведения, определяемого реализацией. Ваш код с #pragma может скомпилироваться в одном компиляторе, но может не скомпилироваться в другом.

person Donotalo    schedule 01.08.2011
comment
Разве настройка разделов .data и .bss не выполняется исполняемым загрузчиком, а не кодом запуска? - person DevSolar; 01.08.2011
comment
@devsolar: это может быть не всегда так. например микроконтроллеры. Я работал с микроконтроллерами OKI 411, OKI 431 и PIC16F. Все они имеют какой-то код запуска/времени выполнения. Кстати, я не знаю, как это обычно достигается при программировании для ПК. Я только слышал об именах .data и .bss, мало о них знаю. не могли бы вы дать мне ссылку, из которой я могу узнать больше? - person Donotalo; 01.08.2011
comment
Базовый макет объектного файла ELF: раздел .text содержит машинный код, .data содержит данные инициализации (10 в вашем примере). .bss — это нулевая инициализируемая область, которой, конечно, нет в исполняемом файле, вернее, только как число размера; вы оставляете это загрузчику, чтобы предоставить достаточно памяти с нулевой инициализацией. Реальность, конечно, сложнее (разделы, содержащие отладочную информацию, или обработку исключений C++, или что-то в этом роде). Проверьте Википедию, сегмент данных. - person DevSolar; 02.08.2011

Что касается стандарта ISO C, точка входа для программы C всегда main (если для ее переопределения не используется какая-либо функция, определяемая реализацией) для размещенной реализации. Для «автономной реализации» (обычно встроенной системы, часто без операционной системы) точка входа определяется реализацией.

person Keith Thompson    schedule 02.08.2011