Во многих примерах кода на сайте встречаются как записи вида void main()
, так и int main()
для главной функции программы.
Какой из них правильный и в чём вообще разница?
Стандарт языка требует обязательного наличия двух возможных реализаций:
int main()
int main(int, char**)
То есть в обоих случаях возвращаемым типом является int
. Однако, разрешается существование и дополнительных вариантов в том или ином компиляторе:
Its type shall have C++ language linkage and it shall have a declared return type of type int
, but otherwise its type is implementation-defined.
Таким образом, вариант, возвращающий int
является переносимым между разными реализациями компиляторов, а void
к таковым не относится. Но в частности void main()
поддерживается компилятором Microsoft Visual C++.
Возвращаемое значение main
в общем случае говорит об успешности работы программы. Если всё прошло хорошо, то возвращается ноль - return 0;
; иначе следует вернуть какое-то другое целочисленное значение, которое можно обработать на стороне, вызвавшей программу. Разрешается явно не писать return 0;
в main
. В таком случае, при выходе из функции 0
будет подразумеваться. Аналогичное поведение распространяется и на void
вариант от MS. Но если в случае с int
код возврата можно вернуть явно через return
, то с void main()
такой вариант уже не пройдет:
error C2562: 'main': 'void' function returning a value
Правда, вместо этого можно использовать функцию exit(0)
, которая прерывает выполнение программы и возвращает переданный код вызывающей стороне.
Данная проблема является проблемой линковщика, а не компилятора.
Нужно понимать, что main является _cdecl
функцией, т.е. функции всёравно сколько параметров, потому что, опорная библиотека будет иметь примерно такой вид
push ecx; argv
push eax; argc
call _main
pop ecx
pop ecx
push eax ; Код возрата
call _exit ; И на выход с кодом возврата
Т.е. фактически если ф-ция будет int main()
- стек не испортится, просто функция не увидит argv и argc. А функция void main(int argc, int argv)
получит оба параметра.
Так как опора идет на сигнатуру _main, то на эту сигнатуру можно посадить любую функцию, которая или не имеет параметров, или имеет метку _cdecl (если это не запретит компилятор). Для получения такой сигнатуры нужно указать что используются страрые сигнатуры, делается это указанием extern "C"
(это указание присутствует в стандартных библиотеках, благодаря которым main и срабатывает). Т.е. могут прокатить виды extern "C" int _cdecl main(...); int _cdecl main(...){}
а так же аналогично void main()
, int main(int argc)
и даже long _cdecl main(...);
, int _cdecl main(int argc, char** argv, int secparam1, int secparam2, int secparam3)
Теперь о возвращаемом типе. Опорная библиотека ожидает, что в eax прийдет результат. При использовании void
- программа может вернуть "мусор", который вернётся из eax, с этой точки зрения int main()
лучше. Но последнее время, код возврата программы нигде не анализируется, поэтому если ф-ция вернула "мусор" - это с большой вероятностью ни на что не повлияет.
Если вы пишите под батник, или под програмный комплекс (инсталятор например) , где проверяется код возврата - то нужно писать int main()
и возвращать нужные значения.
Так же, есть функции exit
terminate
, и есть обработчики исключений, которые прерыват программу в обход main
- если программа прерывается всегда "насильно" - то возвращаемый тип перестаёт играть свою роль.
Айфон мало держит заряд, разбираемся с проблемой вместе с AppLab
Вопрос заключается в том, как правильно реализовать Getter для указателя, чтобы он был "безопасным"Под безопасностью я подразумеваю предотвращение...
Есть вектор std::vector<uint8_t> From; Он содержит 10^9 элементов