Законно ли C ++ объявлять main как extern «C»?

17

Будучи программистом низкого уровня, я часто работаю с кодом запуска модуля для исполняемых файлов, поэтому я прекрасно понимаю, как работает код, подобный "crt0". При написании кода на C ++ я обычно объявлял main как extern "C" , чтобы соответствовать тому, что код запуска C собирается сделать для вызова main . Поэтому я обычно использую это объявление для mainwmain , если специально нацелено на Windows):

extern "C" int main(int argv, const char *const *argv)

extern "C" int __cdecl wmain(int argv, const wchar_t *const *argv)

Законно ли использовать extern "C" на main ? Кроме того, является ли const char *const * допустимым для типа argv, в отличие от char *[] ?

    
задан Myria 06.11.2013 в 04:24
источник
  • const char * const * argv должен быть законным, хотя вы можете захотеть сохранить его на char * const * argv по практическим соображениям, в частности, тот факт, что если вы когда-либо используете getopt или аналогичный, этот первый const убьет вас. –  Charlie 06.11.2013 в 04:29
  • Вы действительно не хотите код запуска C. Вам нужно запустить конструкторы globals для запуска, и это делается с помощью кода запуска C ++. Другое дело, как правило, проблем не существует. На языке C нет ничего, что создавало проблемы для кода запуска C ++. –  MSalters 06.11.2013 в 10:06
  • См. также Что должно main () возвращать в C и C ++. –  Jonathan Leffler 31.05.2016 в 04:27

3 ответа

6

Связь определяется реализацией (3.6.1p3):

The linkage (3.5) of main is implementation-defined.

Кроме того, для вашего последнего вопроса вполне допустимо иметь const char* const* (3.6.1p2):

An implementation shall not predefine the main function. This function shall not be overloaded. It shall have a return type of type int, but otherwise its type is implementation-defined.

    
ответ дан Jesse Good 06.11.2013 в 04:28
4

Стандарт благословляет две формы main :

int main()
int main(int argc, char* argv[])

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

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

    
ответ дан n.m. 06.11.2013 в 05:26
  • Windows, в частности, кажется, рассматривает main () как extern «C» void __cdecl main (), а MS-специфичный WinMain () как extern «C» void __stdcall WinMain (), судя по искаженным именам (_main и _WinMain @ 16, соответственно). Я подозреваю, что это ограничение CRT, предназначенного для работы с кодом C и C ++. [wmain и wWinMain обрабатываются одинаково с основным и WinMain.] –  Justin Time 05.05.2016 в 19:06
3

extern "C" только указывает компилятору C ++, что он НЕ должен украшать или использовать преобразование имен в сгенерированных метках функций.

Да, оба законны.

    
ответ дан Aniket Inge 06.11.2013 в 04:27
  • На самом деле, он также может изменить соглашение о вызове: стандартное соглашение C ++ по умолчанию не должно быть совместимо с C, только extern «C» обеспечивает это. –  syam 06.11.2013 в 04:29
  • @syam согласился! ... –  Aniket Inge 06.11.2013 в 04:29