2012-01-03 2 views
20

В объектно-ориентированных языках (C++) вы можете выполнить код до main() с помощью глобального объекта или статического объекта класса и иметь свои конструкторы для запуска кода, который вы хотите.Выполнение кода до main()

Есть ли способ сделать это в C? У меня нет конкретной проблемы, которую я пытаюсь решить, мне просто интересно. Одно может быть полезно для автоматической инициализации библиотеки.

+0

http://stackoverflow.com/questions/949890/how-can-i-perform-pre-main-initialization-in-cc-with-avr-gcc – stacker

+0

@stacker - Вопрос, на который вы ссылаетесь, специфичен для Arduino. Во всяком случае, ответы там могут быть полезными. – mouviciel

ответ

10

Существуют способы использования __attribute__, но они очень специфичны для вашего компилятора и кода, который написан с использованием этих не действительно портативный. С другой стороны, язык C не предоставляет никаких пусковых модулей/библиотек.

В C логически main() - это первая функция, вызываемая ОС. Но перед вызовом main() ОС вызывает другую функцию с именем start-up для настройки различных переменных среды, инициализации (неинициализированных) статических переменных, создания фрейма стека (записи активации) и инициализации указателя стека на начало области стека и других задачи, которые необходимо выполнить перед вызовом main().

Скажите, если вы пишете код для встроенных систем, где для выполнения вышеупомянутой работы нет или минимальной ОС, вы должны изучить эти параметры, зависящие от компилятора. Помимо компиляторов GCC, Turbo-C и Microsoft C предусмотрены средства для добавления кода на конкретный аппаратный компьютер (например, 8086 машин).

IOW, пусковые модули не предназначены для программистов.

+0

Неверно, 'main' не является первой функцией, вызываемой ОС. Вы слышали о [crt0] (https://en.wikipedia.org/wiki/Crt0)? '_start' всегда вызывается перед' main', а в Windows 'WinMain' вызывается до' main'. –

0

Вы можете инициализировать глобальные переменные, но не вызывать функции внутри этих инициализаций.

1

Нет, вы не можете сделать это в C, и я бы сказал, что вы действительно не можете получить этот «код для выполнения до main()» даже в C++. Да, это могло бы появляться до main() в скрипте, но main() - это где программа на самом деле начинается.

Теперь вы можете инициализировать значения, что возможно. Вы также можете иметь переменные с заранее заданным состоянием, но это не одно и то же.

+3

Per 3.6.2/3 («это должно произойти до первого использования какой-либо функции или объекта, определенного в той же самой единицы перевода, что и объект, подлежащий инициализации»), объекты с областью пространства имен в том же TU, что и 'main', должны быть инициализируется до первого утверждения 'main', так как' main' * является * функцией в том же TU. Стандарту все равно, есть ли вызов этого кода инициализации внутри тела функции 'main', перед любыми другими операторами или есть ли какая-либо другая функция для выполнения init, которую выполняет вызов перед вызовом main. –

4

С помощью gcc вы можете сделать это, используя атрибут функции конструктора, например.

__attribute__ ((__constructor__)) 
void foo(void) { 
     ... 
} 

Это вызовет foo перед основным.

Примечание: Возможно, это не переносится на другие компиляторы.

13

Вы можете сделать это с помощью __attribute__ ((constructor)). Я проверил следующий пример как с gcc, так и с clang. Это, как говорится, это не часть языка.

#include <stdio.h> 

void __attribute__ ((constructor)) premain() 
{ 
    printf("premain()\n"); 
} 

int main(int argc, char *argv[]) 
{ 
    printf("main()\n"); 
    return 0; 
} 

Он делает следующее:

$ ./test 
premain() 
main() 
0

Ни в стандартах совместимый способ, но вы должны закопать к тому, что на самом деле происходит, когда ваша операционная система загружает двоичный образ и вызывает главную функцию приложения !

0

Есть переносные способы указания функций, которые могут быть выполнены после выполнения основного.

  1. atexit()

  2. at_quick_exit()

Далее следуют this ссылке и о различных типах инициализации в C++ - что может быть полезно для вас, чтобы выполнить код перед основной() называется ,

+0

Далее следуйте этой [link] (http://en.cppreference.com/w/cpp/language/initialization) и о различных типах инициализации на C++ - это может быть полезно для выполнения кода перед тем, как main() будет называется. –

+0

Вопрос состоял в том, чтобы вызвать код до main в C. Не вызывать код после main или C++. –

Смежные вопросы