C++ объявляет "main" как ссылку на функцию?
Что делать, если я определяю main как ссылку на функцию?
#include<iostream>
#include<cstring>
using namespace std;
int main1()
{
cout << "Hello World from main1 function!" << endl;
return 0;
}
int (&main)() = main1;
что будет? Я тестировал в онлайн-компиляторе с ошибкой "ошибка сегментации":
и под VC++ 2013 он создаст сбой программы во время выполнения!
код, вызывающий данные указателя функции в качестве кода, будет скомпилирован, который немедленно завершит работу при запуске.
я также хотел бы стандартную цитату ISO C++ об этом.
концепция будет полезна, если вы хотите определить любую из 2 точек входа в зависимости от некоторого макроса, как это:
int main1();
int main2();
#ifdef _0_ENTRY
int (&main)() = main1;
#else
int (&main)() = main2;
#endif
5 ответов
это не соответствующая программа на C++. C++ требует этого (раздел 3.6.1)
программа должна содержать глобальную функцию
main
ваша программа содержит глобальную не-функцию под названием main
, который вводит конфликт имени с main
функция, которая требуется.
одним из оправданий этого было бы то, что он позволяет размещенной среде во время запуска программы выполнять вызов функции к main
. Это не эквивалентно исходной строке main(args)
который может быть вызовом функции, разыменование указателя функции, использование operator()
на объекте функции или построение экземпляра типа main
. Нет,main
должно быть функцией.
еще одна вещь, чтобы отметить, что стандарт C++ никогда не говорит, что тип main
на самом деле есть, и мешает вам его наблюдать. Так что реализации могут (и делают!) перепишите подпись, например добавив любую из int argc, char** argv, char** envp
что вы опустили. Ясно, что он не мог знать, чтобы сделать это для вашего main1
и main2
.
Это было бы полезно, если вы хотите определить любую из 2 точек входа в зависимости от некоторого макроса
нет, не правда. Вы должны сделать это:
int main1();
int main2();
#ifdef _0_ENTRY
int main() { return main1(); }
#else
int main() { return main2(); }
#endif
это скоро станет явно плохо образованной, благодаря разрешению CWG выпуск 1886, в настоящее время в статусе" предварительно готов", который добавляет, среди прочего, следующее к [basic.начать.main]:
программа, которая объявляет переменную
main
в глобальном масштабе или что объявляет имяmain
с связью языка C (в любом пространстве имен) является плохо сформирована.
что будет на практике сильно зависит от реализации.
в вашем случае ваш компилятор, по-видимому, реализует эту ссылку как "замаскированный указатель". Кроме того, указатель имеет внешнюю связь. Т. е. ваша программа экспортирует внешний символ под названием main
, который фактически связан с ячейки памяти в сегменте данных, занимаемый указателем. Компоновщик, не слишком вглядываясь в него, записывает это местоположение памяти как запись программы точка.
позже попытка использовать это местоположение в качестве точки входа вызывает ошибку сегментации. Во-первых, в этом месте нет значимого кода. Во-вторых, простая попытка передать управление в местоположение внутри сегмента данных может вызвать механизмы "защиты выполнения данных" вашей платформы.
делая это, вы, по-видимому, надеялись, что ссылка будет оптимизирована, т. е. что main
станет просто другим именем для main1
. В твоем случае - нет. случаться. Ссылка сохранилась как независимый внешний объект.
похоже, вы уже ответили на вопрос о том, что происходит.
насколько, почему, в коде main
ссылка/указатель на функцию. Это отличается от функции. И я ожидал бы ошибки сегмента, если код вызывает указатель вместо функции.