Я спрашиваю, потому что мой компилятор, кажется, так думает, хотя я этого не делаю.
echo 'int main;' | cc -x c - -Wall
echo 'int main;' | c++ -x c++ - -Wall
Clang не выдает никаких предупреждений или ошибок при этом, а gcc выдает только кроткое предупреждение:, 'main' is usually a function [-Wmain]
но только при компиляции как C. Указание a -std=
не имеет значения.
В противном случае он компилируется и линкуется нормально. Но при выполнении он немедленно завершается SIGBUS
(для меня).
Чтение (отличных) ответов на вопрос, что должно возвращать main () в C и C ++? и беглый просмотр спецификаций языка, мне определенно может показаться , что требуется функция main . Но словоблудие из gcc -Wmain
('main' - обычно функция) (и недостаток ошибок здесь), кажется, вероятно, предполагает иное.
Но почему? Есть ли для этого какое-то странное крайнее или «историческое» применение? Кто-нибудь знает, что дает?
Я полагаю, что я действительно считаю, что это должно быть ошибкой в размещенной среде, а?
gcc -std=c99 -pedantic ...
-pedantic
любым или без него-std
. Моя системаc99
также компилирует это без предупреждений или ошибок ...main
, что вряд ли сработает. Если вы инициализируете main с «правильным» значением, он может действительно вернуть ...main
)main=195;
Ответы:
Поскольку вопрос помечен двойными тегами как C и C ++, рассуждения для C ++ и C будут разными:
xyz
и отдельную глобальную функциюxyz(int)
. Однако имяmain
никогда не искажается.Вот что здесь происходит: компоновщик ожидает найти символ
main
, и он это делает. Он «связывает» этот символ, как будто это функция, потому что он ничего не знает. Часть библиотеки времени выполнения, которая передает управлениеmain
запрашивающему компоновщикуmain
, поэтому компоновщик предоставляет ему символmain
, позволяя завершиться фазе компоновки. Конечно, это не удается во время выполнения, потому чтоmain
это не функция.Вот еще одна иллюстрация той же проблемы:
файл xc:
файл yc:
компиляции:
Это компилируется и, вероятно, будет работать, но это поведение undefined, потому что тип символа, обещанного компилятору, отличается от фактического символа, предоставленного компоновщику.
Что касается предупреждения, я думаю, что это разумно: C позволяет создавать библиотеки, у которых нет
main
функций, поэтому компилятор освобождает имяmain
для других целей, если вам нужно определить переменнуюmain
по неизвестной причине.источник
main
не подлежат искажению имени (как кажется) в C ++, независимо от того, является ли это функцией.main
что-либо, кроме функции. Ответ предлагает объяснение обеих частей.main
не зарезервированное слово это просто предопределенный идентификатор (напримерcin
,endl
,npos
...), так что вы можете объявить переменнуюmain
, инициализировать его , а затем распечатать его значение.Конечно:
main()
функции (библиотеки).РЕДАКТИРОВАТЬ
Некоторые ссылки:
main
не является зарезервированным словом (C ++ 11):C ++ 11 - [basic.start.main] 3.6.1.3
Зарезервированные слова в языках программирования .
Зарезервированные слова не могут быть переопределены программистом, но предопределенные часто могут быть переопределены в некоторой степени. Это случай
main
: существуют области, в которых объявление, использующее этот идентификатор, переопределяет его значение.источник
main()
функция, но вы не можете связать его как программу. То , что здесь происходит то , что программа «действует» в настоящее время связана безmain()
, простоmain
.cin
иendl
не находятся в пространстве имен по умолчанию - они находятся вstd
пространстве имен.npos
является членомstd::basic_string
.main
будет зарезервирован в качестве глобального имени. Ни одна из других вещей, которые вы упомянули, неmain
предопределена.main
разрешено. C ++ говорит: «Реализация не должна предопределять основную функцию», а C говорит: «Реализация не объявляет прототип для этой функции».Подходит ли программа
int main;
на C / C ++?Не совсем понятно, что такое программа на C / C ++.
Подходит
int main;
ли программа C?Да. Такая программа допускается в автономном исполнении.
main
не должно иметь особого значения в отдельно стоящей среде.Это недопустимо в размещенной среде.
Это
int main;
действующая программа на C ++?То же самое.
Почему вылетает?
Программа не обязательно должна иметь смысл в вашей среде. В автономной среде запуск и завершение программы, а также значение
main
определяются реализацией.Почему компилятор меня предупреждает?
Компилятор может предупреждать вас обо всем, что ему заблагорассудится, если только он не отклоняет соответствующие программы. С другой стороны, предупреждение - это все, что требуется для диагностики несоответствующей программы. Поскольку эта единица трансляции не может быть частью действующей размещенной программы, диагностическое сообщение оправдано.
Это
gcc
автономная среда или размещенная среда?Да.
gcc
документирует-ffreestanding
флаг компиляции. Добавьте его, и предупреждение исчезнет. Вы можете использовать его при сборке, например, ядер или прошивки.g++
не документирует такой флаг. Поставка, похоже, не влияет на эту программу. Вероятно, можно с уверенностью предположить, что среда, предоставляемая g ++, размещена. Отсутствие диагностики в этом случае - ошибка.источник
Это предупреждение, поскольку технически это не запрещено. Код запуска будет использовать расположение символа «main» и перейдет к нему с тремя стандартными аргументами (argc, argv и envp). Это не так, и во время компоновки не может проверить, действительно ли это функция, или даже что у нее есть эти аргументы. Вот почему работает int main (int argc, char ** argv) - компилятор не знает об аргументе envp, и он просто не используется, и это очистка вызывающего.
В шутку можно сделать что-нибудь вроде
на машине x86 и, игнорируя предупреждения и тому подобное, он не просто компилируется, но и работает.
Кто-то использовал похожую технику для написания исполняемого файла (вроде того), который работает напрямую на нескольких архитектурах - http://phrack.org/issues/57/17.html#article . Он также был использован для победы в IOCCC - http://www.ioccc.org/1984/mullender/mullender.c .
источник
int main __attribute__ ((section (".text")))= 0xC3C3C3C3;
Это действующая программа?
Нет.
Это не программа, поскольку в ней нет исполняемых частей.
Допустимо ли компилировать?
Да.
Можно ли его использовать с действующей программой?
Да.
Не весь скомпилированный код должен быть исполняемым, чтобы быть действительным. Примерами являются статические и динамические библиотеки.
Вы фактически создали объектный файл. Это недопустимый исполняемый файл, однако другая программа может ссылаться на объект
main
в результирующем файле, загружая его во время выполнения.Это должно быть ошибкой?
Традиционно C ++ позволяет пользователю делать вещи, которые могут показаться бесполезными, но которые соответствуют синтаксису языка.
Я имею в виду, конечно, это можно было бы переклассифицировать как ошибку, но почему? Какой цели это могло бы служить, если предупреждение не служило?
Пока существует теоретическая возможность использования этой функции в реальном коде, очень маловероятно, что вызов нефункционального объекта
main
приведет к ошибке в зависимости от языка.источник
main
. Как действительная программа, которая должна быть внешне видимая функция с именемmain
, ссылка на него?main
функцию.int main;
определение не будет видно.Я хотел бы добавить к уже полученным ответам, сославшись на действующие языковые стандарты.
Это int main; действующая программа на C?
Краткий ответ (мое мнение): только если в вашей реализации используется «автономная среда выполнения».
Все следующие цитаты из C11
5. Окружающая среда
5.1.2 Среда выполнения
5.1.2.1 Отдельностоящая среда
5.1.2.2 Размещенная среда
5.1.2.2.1 Запуск программы
Из них наблюдается следующее:
В автономной среде выполнения я бы сказал, что это допустимая программа, которая не позволяет запускать, потому что для этого нет функции, требуемой в 5.1.2. В размещенной среде выполнения, хотя ваш код представляет объект с именем main , он не может предоставить возвращаемое значение, поэтому я бы сказал, что это недопустимая программа в этом смысле, хотя можно было бы также утверждать, как раньше, если программа не предназначено для выполнения (например, может потребоваться предоставить данные), тогда это просто не позволяет сделать это.
Это int main; действующая программа на C ++?
Краткий ответ (мое мнение): только если в вашей реализации используется «автономная среда выполнения».
Цитата из C ++ 14
3.6.1 Основная функция
Здесь, в отличие от стандарта C11, меньше ограничений применяется к автономной среде выполнения, поскольку функция запуска не упоминается вообще, в то время как для размещенной среды выполнения ситуация в значительной степени такая же, как для C11.
Опять же, я бы сказал, что для размещенного случая ваш код не является допустимой программой на C ++ 14, но я уверен, что он предназначен для автономного случая.
Поскольку в моем ответе рассматривается только среда выполнения , я думаю, что ответ dasblinkenlicht вступает в игру, так как изменение имени происходит в среде перевода заранее. Здесь я не уверен, что приведенные выше цитаты соблюдаются так строго.
источник
Ошибка твоя. Вы не указали функцию с именем,
main
которая возвращает,int
и пытались использовать вашу программу в размещенной среде.Предположим, у вас есть модуль компиляции, который определяет глобальную переменную с именем
main
. Это вполне может быть законным в автономной среде, потому что то, что составляет программу, остается на усмотрение реализации в автономной среде.Предположим, у вас есть другой модуль компиляции, который определяет глобальную функцию с именем,
main
которая возвращаетint
и не принимает аргументов. Это именно то, что нужно программе в размещенной среде.Все в порядке, если вы используете только первую единицу компиляции в автономной среде и только вторую в размещенной среде. Что, если вы используете оба в одной программе? В C ++ вы нарушили одно правило определения. Это неопределенное поведение. В C вы нарушили правило, согласно которому все ссылки на один символ должны быть согласованными; если нет, это неопределенное поведение. Неопределенное поведение - это «выйди из тюрьмы, бесплатно!» карточка разработчикам реализации. Все, что делает реализация в ответ на неопределенное поведение, соответствует стандарту. Реализация не должна предупреждать, не говоря уже об обнаружении неопределенного поведения.
Что, если вы используете только одну из этих единиц компиляции, но используете неправильную (что вы и сделали)? В C ситуация ясна. Неспособность определить функцию
main
в одной из двух стандартных форм в размещенной среде является неопределенным поведением. Предположим, вы вообще не определилиmain
. Компилятор / компоновщик ничего не говорит об этой ошибке. То, что они действительно жалуются, - это их вежливость. То, что программа на C скомпилирована и скомпилирована без ошибок, является вашей ошибкой, а не компилятором.В C ++ это немного менее ясно, потому что неспособность определить функцию
main
в размещенной среде является ошибкой, а не неопределенным поведением (другими словами, это должно быть диагностировано). Однако одно правило определения в C ++ означает, что компоновщики могут быть довольно тупыми. Работа компоновщика заключается в разрешении внешних ссылок, и благодаря единому правилу определения компоновщик не должен знать, что означают эти символы. Вы предоставили символ с именемmain
, компоновщик ожидает увидеть символ с именемmain
, так что с компоновщиком все хорошо.источник
Для C пока это поведение, определяемое реализацией.
Как сказано в ISO / IEC9899:
источник
Нет, это недействительная программа.
Для C ++ это было недавно явно сделано неправильно в отчете о дефекте 1886: Языковая привязка для main (), в котором говорится:
и часть постановления включала следующее изменение:
Мы можем найти эту формулировку в последнем проекте стандарта C ++ N4527, который представляет собой проект C ++ 1z.
В последних версиях clang и gcc теперь возникает ошибка ( см. Вживую ):
До этого отчета о дефектах это было неопределенное поведение, не требующее диагностики. С другой стороны, плохо сформированный код требует диагностики, компилятор может сделать это либо предупреждением, либо ошибкой.
источник
main()
.) Я понимаю причины запрета наmain()
наличие явной спецификации связывания, но не понимаю, что это требуетmain()
наличия связи C ++ . Конечно , стандарт не непосредственно адрес , как обращаться с ABI связь / имя коверкая, но на практике (скажем, с Itanium ABI) это будет искажатьmain()
к_Z4mainv
. Что мне не хватает?