Раздел $ 3.6.1 / 1 стандарта C ++ гласит:
Программа должна содержать глобальную функцию с именем main , которая является назначенным запуском программы.
Теперь рассмотрим этот код,
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()
функцию, которая должна быть «запуском» программы.
Я также скомпилировал его с -pedantic
опцией GCC 4.5.0. Это не выдает ошибок, даже предупреждений!
Итак, мой вопрос:
Действительно ли этот код соответствует стандарту?
Если он соответствует стандарту, разве это не отменяет того, что говорит стандарт? main()
это не запуск этой программы! user_main()
выполнен до main()
.
Я понимаю , что для инициализации глобальную переменную main_ret
, в use_main()
сначала выполняется , но это совсем другое дело; Дело в том, что он делает недействительным цитируемый оператор $ 3.6.1 / 1 из Стандарта, поскольку main()
НЕ является началом программы; это фактически конец из этой программы!
РЕДАКТИРОВАТЬ:
Как вы определяете слово «старт»?
Все сводится к определению слова «запуск программы» . Так как именно вы это определяете?
main()
как «начало программы»static
продолжительность хранения, и поэтому эти объекты, принадлежащие разным единицам трансляции, могут быть инициализированы в любом порядке (поскольку порядок не определен стандартом). Я не уверен, что это ответ на ваш вопрос, хотя именно это я мог бы сказать в контексте этой темы.Вы неправильно читаете предложение.
Стандарт ОПРЕДЕЛЯЕТ слово «начало» для остальной части стандарта. Это не говорит о том, что перед вызовом код не выполняется
main
. В нем говорится, что запуск программы считается на функцииmain
.Ваша программа соответствует требованиям. Ваша программа не «запустилась» до тех пор, пока не запустится main. Конструктор вызывается до того, как ваша программа "запускается" в соответствии с определением "start" в стандарте, но это не имеет значения. МНОГО кода выполняется перед
main
как всегда вызывается в каждой программе, а не только этот пример.Для целей обсуждения код вашего конструктора выполняется до «запуска» программы, и это полностью соответствует стандарту.
источник
Ваша программа не будет связываться и, следовательно, не будет работать, если не будет файла main. Однако main () не вызывает начало выполнения программы, потому что у объектов на уровне файла есть конструкторы, которые запускаются заранее, и можно было бы написать всю программу, которая запускает свое время жизни до достижения main (), и позволить самой main иметь пустое тело.
На самом деле, чтобы обеспечить это, вам понадобится один объект, созданный до main, и его конструктор для вызова всего потока программы.
Посмотри на это:
Поток вашей программы будет эффективно вытекать из
Foo::Foo()
источник
Вы также отметили вопрос как «C», тогда, строго говоря о C, ваша инициализация должна завершиться неудачно в соответствии с разделом 6.7.8 «Инициализация» стандарта ISO C99.
Наиболее актуальным в этом случае кажется ограничение №4, которое гласит:
Итак, ответ на ваш вопрос заключается в том, что код не соответствует стандарту C.
Вы, вероятно, захотели бы удалить тег «C», если бы вас интересовал только стандарт C ++.
источник
Раздел 3.6 в целом очень четко описывает взаимодействие
main
и динамические инициализации. «Назначенный запуск программы» больше нигде не используется и просто описывает общее назначениеmain()
. Нет никакого смысла интерпретировать эту фразу нормативным образом, который противоречит более подробным и ясным требованиям Стандарта.источник
Компилятору часто приходится добавлять код перед main (), чтобы соответствовать стандарту. Поскольку в стандарте указано, что инициализация глобальных переменных / статик должна выполняться до выполнения программы. Как уже упоминалось, то же самое касается конструкторов объектов, размещенных в области видимости файла (глобальных объектов).
Таким образом, исходный вопрос является отношением к C , а также, потому что в программе C вы бы еще глобал / статических инициализации , чтобы сделать до того , как программа может быть запущена.
Стандарты предполагают, что эти переменные инициализируются с помощью «магии», потому что они не говорят, как они должны быть установлены перед инициализацией программы. Я думаю, они считали это чем-то выходящим за рамки стандарта языка программирования.
Изменить: см., Например, ISO 9899: 1999 5.1.2:
Теория, лежащая в основе этой «магии», восходит к зарождению C, когда это был язык программирования, предназначенный для использования только для ОС UNIX на компьютерах с ОЗУ. Теоретически программа сможет загрузить все предварительно инициализированные данные из исполняемого файла в ОЗУ одновременно с загрузкой самой программы в ОЗУ.
С тех пор компьютеры и ОС эволюционировали, и C используется в гораздо более широкой области, чем предполагалось изначально. Современная ОС ПК имеет виртуальные адреса и т. Д., И все встроенные системы выполняют код из ПЗУ, а не из ОЗУ. Так что есть много ситуаций, когда оперативную память нельзя настроить «автоматически».
Кроме того, стандарт слишком абстрактен, чтобы что-либо знать о стеках, памяти процесса и т. Д. Эти вещи также должны быть выполнены до запуска программы.
Следовательно, почти каждая программа на C / C ++ имеет некоторый код инициализации / копирования, который выполняется перед вызовом main, чтобы соответствовать правилам инициализации стандартов.
Например, встроенные системы обычно имеют параметр, называемый «запуск без соответствия ISO», при котором вся фаза инициализации пропускается по соображениям производительности, а затем код фактически запускается непосредственно из main. Но такие системы не соответствуют стандартам, поскольку вы не можете полагаться на значения инициализации глобальных / статических переменных.
источник
Ваша «программа» просто возвращает значение из глобальной переменной. Все остальное - это код инициализации. Таким образом, стандарт выполняется - у вас просто очень тривиальная программа и более сложная инициализация.
источник
main () - это пользовательская функция, вызываемая библиотекой времени выполнения C.
см. также: Избегание главного (точки входа) в программе на C
источник
Похоже на придирку с английской семантикой. ОП называет свой блок кода сначала «кодом», а затем «программой». Пользователь пишет код, а затем компилятор пишет программу.
источник
main вызывается после инициализации всех глобальных переменных.
Стандарт не определяет порядок инициализации всех глобальных переменных всех модулей и статически связанных библиотек.
источник
Да, main - это «точка входа» для каждой программы на C ++, за исключением расширений, специфичных для реализации. Тем не менее, некоторые вещи происходят до main, особенно глобальная инициализация, например, main_ret.
источник