Czy main () naprawdę uruchamia program C++?

Sekcja $3.6.1 / 1 ze standardu C++ czyta,

Program zawiera globalną funkcja o nazwie main , która jest wyznaczony start programu.

Rozważmy teraz ten kod,

int square(int i) { return i*i; }
int user_main()
{ 
    for ( int i = 0 ; i < 10 ; ++i )
           std::cout << square(i) << endl;
    return 0;
}
int main_ret= user_main();
int main() 
{
        return main_ret;
}

Ten przykładowy kod robi to, co zamierzam zrobić, tj. wypisuje kwadrat liczb całkowitych od 0 do 9, przed wejściem do funkcji main(), która ma być "startem" programu.

Spójrz na wyjście tutaj: http://www.ideone.com/Niy0R

Skompilowałem go również z opcją -pedantic, GCC 4.5.0. Nie daje żadnego błędu, nawet nie ostrzega!

Więc moje pytanie brzmi:]}

Czy ten kod jest zgodny ze standardem?

Jeśli jest zgodny ze standardem, to czy nie unieważnia tego, co mówi Norma? main() nie jest start tego programu! user_main() wykonane przed main().

Rozumiem, że aby zainicjować zmienną globalną main_ret, use_main() pierwszy wykonuje, ale to zupełnie co innego; chodzi o to, że powoduje unieważnienie cytowanej deklaracji $3.6.1 / 1 ze standardu, ponieważ main() nie jest start programu; w rzeczywistości jest to end tego {43]} programu!


EDIT:

Jak zdefiniować słowo "start"?

Sprowadza się do definicji wyrażenia "start programu" . Więc jak dokładnie to definiujesz?

Author: Nawaz, 2011-01-24

11 answers

Nie, C++ robi wiele rzeczy, aby "ustawić środowisko" przed wywołaniem main; jednak main jest oficjalnym startem "określonej przez użytkownika" części programu C++.

Niektóre ustawienia środowiska nie są sterowalne (jak Początkowy kod do skonfigurowania STD::cout; jednak niektóre środowiska są sterowalne jak statyczne bloki globalne (do inicjalizacji statycznych zmiennych globalnych). Zauważ, że ponieważ nie masz pełnej kontroli przed main, nie masz pełnej kontroli nad zamówieniem w którym inicjowane są statyczne bloki.

Po main, Twój kod jest koncepcyjnie "w pełni kontrolowany" nad programem, w tym sensie, że możesz zarówno określić instrukcje do wykonania, jak i kolejność ich wykonania. Wielowątkowość może zmienić kolejność wykonywania kodu; ale nadal masz kontrolę nad C++, ponieważ określiłeś, że sekcje kodu wykonują się (prawdopodobnie)poza kolejnością.

 78
Author: Edwin Buck,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-01-24 16:11:30

Czytasz zdanie niepoprawnie.

Program zawiera globalną funkcję o nazwie main, , która jest wyznaczonym startem programu.

Standard definiuje słowo "start" na potrzeby pozostałej części standardu. Nie mówi, że żaden kod nie jest wykonywany przed wywołaniem main. Mówi, że początek programu jest uważany za funkcję main.

Twój program jest zgodny. Twój program nie "started" dopóki main nie zostanie uruchomiony. Konstruktor jest wywoływany przed "uruchomieniem" programu zgodnie z definicją "start" w standardzie, ale to nie ma znaczenia. Wiele kodu jest wykonywanych zanim main zostaniekiedykolwiek wywołane w każdym programie, nie tylko w tym przykładzie.

Dla celów dyskusji, Twój kod konstruktora jest wykonywany przed "startem" programu, co jest w pełni zgodne ze standardem.

 84
Author: Adam Davis,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-01-24 16:26:55

Twój program nie połączy się, a tym samym nie uruchomi się, chyba że istnieje main. Jednak main() nie powoduje rozpoczęcia wykonywania programu, ponieważ obiekty na poziomie Pliku mają konstruktory, które uruchamiają się wcześniej i możliwe byłoby napisanie całego programu, który uruchamia swój czas życia przed osiągnięciem main (), a sam main ma puste ciało.

W rzeczywistości, aby to wymusić, musisz mieć jeden obiekt, który jest zbudowany przed main i jego konstruktorem, aby wywołać wszystkie przepływ programu.

Zobacz też:]}
class Foo
{
public:
   Foo();

 // other stuff
};

Foo foo;

int main()
{
}

Przepływ Twojego programu będzie skutecznie wynikał z Foo::Foo()

 23
Author: CashCow,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-01-24 14:58:58

Również otagowałeś pytanie jako "C", więc mówiąc ściśle O C, twoja inicjalizacja powinna się nie udać zgodnie z sekcją 6.7.8 "Inicjalizacja" standardu ISO C99.

Najbardziej istotne w tym przypadku wydaje się ograniczenie # 4, które mówi:

Wszystkie wyrażenia w inicjalizatorze dla obiektu, który ma statyczny czas przechowywania to wyrażenia stałe lub literały łańcuchowe.

Odpowiedź na twoje pytanie brzmi: kod nie jest zgodny z C standard.

Prawdopodobnie chciałbyś usunąć znacznik "C", jeśli interesuje Cię tylko standard C++.

 15
Author: Remo.D,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-01-24 21:56:45

Sekcja 3.6 jako całość jest bardzo jasna na temat interakcji main i dynamicznych inicjalizacji. "Wyznaczony start programu" nie jest używany nigdzie indziej i jest tylko opisem ogólnego zamiaru main(). Nie ma sensu interpretować tego wyrażenia w sposób normatywny, który jest sprzeczny z bardziej szczegółowymi i jasnymi wymaganiami normy.

 10
Author: aschepler,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-01-24 15:37:42

Kompilator często musi dodać kod przed main () do be zgodnego ze standardem. Ponieważ standard określa, że initalizacja globali/statyki musi być wykonana zanim program zostanie uruchomiony. I jak wspomniano, to samo dotyczy konstruktorów obiektów umieszczonych w zakresie plików (globals).

Zatem pierwotne pytanie jest istotne również dla C, ponieważ w programie C nadal będziesz miał globalną / statyczną inicjalizację do zrobienia, zanim program będzie mógł być zaczęło się.

Standardy zakładają, że te zmienne są inicjowane przez "magic", ponieważ nie mówią Jak powinny być ustawione przed inicjalizacją programu. Myślę, że uważali to za coś poza zakresem standardu języka programowania.

Edit: patrz na przykład ISO 9899: 1999 5.1.2:

Wszystkie obiekty ze statycznym magazynem czas trwania zostanie zainicjowany (ustawiony na ich wartości początkowe) przed programem startup. Sposób i termin takie inicjalizacja to inaczej nieokreślone.

Teoria, w jaki sposób ta "magia" miała być wykonana, sięga czasów narodzin C, kiedy był to język programowania przeznaczony do użycia tylko w systemie UNIX, na komputerach opartych na PAMIĘCI RAM. Teoretycznie program byłby w stanie załadować wszystkie wstępnie zainicjowane dane z pliku wykonywalnego DO PAMIĘCI RAM, w tym samym czasie, gdy sam program został przesłany do pamięci RAM.

Od tego czasu Komputery i OS ewoluowały, A C jest używany w znacznie szerszym obszar niż pierwotnie przewidywano. Nowoczesny system operacyjny PC ma wirtualne adresy itp., a wszystkie systemy wbudowane wykonują kod z ROM, nie RAM. Istnieje więc wiele sytuacji, w których pamięci RAM nie można ustawić "automagicznie".

Ponadto standard jest zbyt abstrakcyjny, aby cokolwiek wiedzieć o stosach, pamięci procesów itp. Te rzeczy muszą być również zrobione, zanim program zostanie uruchomiony.

Dlatego prawie każdy program C / C++ ma jakiś kod init/"copy-down", który jest wykonywany przed wywołaniem main, w porządek zgodny z zasadami inicjalizacji norm.

Jako przykład, systemy wbudowane zazwyczaj mają opcję o nazwie "uruchamianie niezgodne z ISO", gdzie cała Faza inicjalizacji jest pomijana ze względu na wydajność, a następnie kod zaczyna się bezpośrednio z main. Ale takie systemy nie są zgodne ze standardami, ponieważ nie można polegać na wartościach init globalnych / statycznych zmiennych.

 9
Author: Lundin,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-01-24 15:47:08

Twój "program" po prostu zwraca wartość ze zmiennej globalnej. Wszystko inne to kod inicjujący. Tak więc standard trzyma - po prostu masz bardzo trywialny program i bardziej złożoną inicjalizację.

 4
Author: Zac Howland,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-01-24 15:14:47

Main () jest funkcją użytkownika wywoływaną przez Bibliotekę uruchomieniową C.

Zobacz też: unikanie głównego (punktu wejścia) w programie C

 4
Author: sylvanaar,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 11:54:28

Wydaje się, że angielska semantyka jest sprzeczna. OP odnosi się do jego bloku kodu najpierw jako "kod", a później jako " program."Użytkownik pisze kod, a następnie kompilator pisze program.

 2
Author: dSerk,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-06-27 01:31:22

Main jest wywoływany po zainicjalizowaniu wszystkich zmiennych globalnych.

To, czego standard nie określa, to kolejność inicjalizacji wszystkich globalnych zmiennych wszystkich modułów i statycznie powiązanych bibliotek.

 1
Author: vz0,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-01-24 22:36:37

Tak, main jest "punktem wejścia" każdego programu C++, z wyjątkiem rozszerzeń specyficznych dla implementacji. Mimo to niektóre rzeczy dzieją się przed main, zwłaszcza globalna inicjalizacja, taka jak dla main_ret.

 0
Author: Fred Nurk,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-01-24 15:01:12