Является ли main () действительно началом программы на C++?


раздел $3.6.1 / 1 из стандарта C++ читает,

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

Теперь рассмотрим этот код

int square(int i) { return i*i; }
int user_main()
{ 
    for ( int i = 0 ; i < 10 ; ++i )
           std::cout << square(i) << endl;
    return 0;
}
int main_ret= user_main();
int main() 
{
        return main_ret;
}

этот пример кода делает то, что я намереваюсь сделать, т. е. печать квадрата целых чисел от 0 до 9,до заключения main() функция, которая должна быть "запуск" программы.

посмотрите на вывод здесь:http://www.ideone.com/Niy0R

я скомпилировал его с -pedantic опция, GCC 4.5.0. Это не дает никакой ошибки, даже не предупреждение!

так что мой вопрос,

действительно ли этот код соответствует стандарту?

если он соответствует стандарту, то не делает ли он недействительным то, что говорит стандарт? main() это не запуск этой программы! user_main() выполнена перед main().

Я понимаю, что для инициализации глобальной переменной main_ret на use_main() сначала выполняется, но это совсем другое дело; дело в том, что это тут признать недействительным цитируемое утверждение $3.6.1 / 1 из стандарта, как main() это не старт программы; это на самом деле конец на этой

11 125

11 ответов:

нет, C++ делает много вещей ,чтобы" установить среду "до вызова main; однако main является официальным запуском" указанной Пользователем " части программы C++.

некоторые настройки среды не управляются (например, начальный код для настройки std:: cout; однако некоторые из сред управляются как статические глобальные блоки (для инициализации статических глобальных переменных). Обратите внимание, что поскольку у вас нет полного контроля до main, у вас нет полного контроля порядок инициализации статических блоков.

после main ваш код концептуально "полностью контролирует" программу, в том смысле, что вы можете указать как инструкции, которые будут выполняться, так и порядок их выполнения. Многопоточность может изменить порядок выполнения кода; но вы все еще контролируете C++, потому что вы указали, что разделы кода выполняются (возможно) вне порядка.

Вы читаете предложение неправильно.

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

стандарт определяет слово "начало" для целей остальной части стандарта. Он не говорит, что никакой код не выполняется до main называется. В нем говорится, что запуск программы считается по функции main.

ваша программа является уступчивым. Ваша программа не "запустилась", пока не будет запущена main. Конструктор вызывается до того, как ваша программа "запускается" в соответствии с определением "start" в стандарте, но это вряд ли имеет значение. Много кода выполняется до main и когда-нибудь вызывается в каждой программе, а не только в этом примере.

в целях обсуждения, ваш код конструктора выполняется до "запуска" программы, и это полностью соответствует норматив.

ваша программа не будет связываться и, следовательно, не запускается, если нет основного. Однако main() не вызывает начало выполнения программы, потому что объекты на уровне файлов имеют конструкторы, которые запускаются заранее, и можно было бы написать всю программу, которая выполняет свое время жизни до достижения main (), и пусть сам main имеет пустое тело.

на самом деле для обеспечения этого вам нужно будет иметь один объект, который построен до main и его конструктора, чтобы вызовите весь поток программы.

посмотри на это:

class Foo
{
public:
   Foo();

 // other stuff
};

Foo foo;

int main()
{
}

поток вашей программы будет эффективно вытекать из Foo::Foo()

вы также отметили вопрос как "C", а затем, говоря строго о C, ваша инициализация должна завершиться неудачей в соответствии с разделом 6.7.8" инициализация " стандарта ISO C99.

наиболее актуальным в данном случае представляется ограничение #4, который говорит:

все выражения в инициализаторе объекта, имеет статическую длительность хранения должны быть постоянными выражениями или строковыми литералами.

Итак, ответ на ваш вопрос заключается в том, что код не соответствует стандарту C.

вы, вероятно, захотите удалить тег "C", если вас интересует только стандарт C++.

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

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

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

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

Edit: см. например ISO 9899:1999 5.1.2:

все объекты со статическим хранилищем длительность должна быть инициализирована (установлена в их первоначальный значения) перед программой запуск. Способ и сроки проведения таких инициализация в противном случае неопределенный.

теория, лежащая в основе того, как это "волшебство" должно было быть сделано, восходит к рождению C, когда это был язык программирования, предназначенный для использования только для ОС UNIX, на компьютерах на базе ОЗУ. Теоретически, программа сможет загружать все предварительно инициализированные данные из исполняемого файла в оперативную память одновременно с загрузкой самой программы БАРАН.

с тех пор компьютеры и ОС эволюционировали, и C используется в гораздо более широкой области, чем первоначально предполагалось. Современная ОС ПК имеет виртуальные адреса и т. д., И все встроенные системы выполняют код из ПЗУ, а не из ОЗУ. Так что есть много ситуаций, когда ОЗУ не может быть установлен "автоматически".

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

, почти каждая программа C / C++ имеет некоторый код init / "copy-down", который выполняется до вызова main, чтобы соответствовать правилам инициализации стандартов.

например, встроенные системы обычно имеют опцию "запуск, не соответствующий ISO", где вся фаза инициализации пропускается по соображениям производительности, а затем код фактически запускается непосредственно из main. Но такие системы не соответствуют стандартам, так как вы не можете полагаться на значения init глобальные / статические переменные.

ваша "программа" просто возвращает значение из глобальной переменной. Все остальное-это код инициализации. Таким образом, стандарт держится - у вас просто очень тривиальная программа и более сложная инициализация.

main () - это пользовательская функция, вызываемая библиотеки C времени выполнения.

Читайте также: избегая главного (точки входа) в программе C

похоже на английскую семантику придирки. ОП ссылается на свой блок кода сначала как" код", а затем как "программа"."Пользователь пишет код, а затем компилятор пишет программу.

main вызывается после инициализации всех глобальных переменных.

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

да, main - это "точка входа" каждой программы на C++, за исключением специфичных для реализации расширений. Тем не менее, некоторые вещи происходят до main, особенно глобальная инициализация, такая как для main_ret.