Вызывать main () сам в c ++? - PullRequest
       33

Вызывать main () сам в c ++?

12 голосов
/ 28 марта 2010
#include <iostream>
#include <cstdlib>

int main() {
    cout << "!!!Hello World!!!" << endl;
    system("pause");
    return main();
}

Вышеописанное работает, но оно жестко закодировано функцией main(). Существует ли магическая переменная или макрос для получения текущей запущенной функции?

Ответы [ 4 ]

12 голосов
/ 25 апреля 2012

Разрешено ли в "C ++"? Нет.

На практике, вы можете позвонить main()? Да.

Что бы ни говорил стандарт C ++, это не мешает компилятору Linux g ++ компилировать код с main() в main().

#include <cstdlib>
#include <iostream>
using namespace std;
int main()
{
 int y = rand() % 10; // returns 3, then 6, then 7
 cout << "y = " << y << endl;
 return (y == 7) ? 0 : main();
}

Что позволяет нам делать:

 > g++ g.cpp; ./a.out
 y = 3
 y = 6
 y = 7

Глядя на сборку, мы видим, что main вызывается так же, как и любая другая функция:

main:
        ...
        cmpl    $7, -12(%rbp)
        je      .L7
        call    main
        ...
.L7:
        ...
        leave
        ret

Не то чтобы это поведение гарантировалось, но похоже, что g ++, похоже, не особо заботится о стандарте, кроме этого саркастического предупреждения с -pedantic

g.cpp:8: error: ISO C++ forbids taking address of function '::main'
12 голосов
/ 28 марта 2010

Стандарт C ++ говорит, что вы не можете вызывать main () из своего собственного кода. Что касается получения имени текущей функции, вы можете использовать макрос __FUNCTION__, но, опять же, это не стандарт:

#include <iostream>
using namespace std;

void foo() {
   cout << __FUNCTION__ << endl;
}

int main() {
   foo();
}

должен печатать "foo" или что-то подобное, если поддерживается __FUNCTION__.

4 голосов
/ 12 сентября 2016

Если конкретная реализация допускает это, она ведет себя неправильно (a) . Стандартное состояние совершенно явно в C++14, 3.6.1 Main function /3:

Функция main не должна использоваться в программе.


(a) Имейте в виду, что многие реализации слабо следуют некоторым частям стандарта, предпочитая силу строгости. Это может иметь неблагоприятный побочный эффект: ваш код не может быть переносим на другие компиляторы или даже на другие версии того же компилятора.

Многие реализации также позволят вам принять более строгий режим, например, использовать g++ -std=c++11 -Werror=pedantic, который улавливает конкретную проблему, купленную в этом вопросе, а также довольно много других. Именно этот «режим» перевода позволяет реализациям претендовать на соответствие стандарту согласно 1.4 Implementation compliance:

Если программа содержит нарушение какого-либо диагностируемого правила ..., соответствующая реализация должна выдать хотя бы одно диагностическое сообщение.

Вы увидите, что в этом случае все еще возможно разрешить компиляцию и запуск кода, поскольку «диагностическое сообщение» может означать скорее предупреждение, чем ошибку.

0 голосов
/ 28 марта 2010

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

func = "my_function"; 
func(); 

если имя вызываемой функции изменится во время выполнения. (Есть исключения и способы обойти это, но вам это не нужно).

Не думайте об этом как о жестком кодировании: это не так. Если вам нужно вызвать функцию, то вы просто пишете ее имя и не пытаетесь абстрагировать ее или что-то в этом роде.

Кроме того, теперь было бы хорошим способом узнать о цикле while, бесконечных циклах и писать вообще без вызовов функций, например,

int main()
{
    while (1) {
        cout << "!!!Hello World!!!" << endl; // prints !!!Hello World!!!
        system("pause");
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...