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 ссылка/указатель на функцию. Это отличается от функции. И я ожидал бы ошибки сегмента, если код вызывает указатель вместо функции.