(Добавление к ответу Джона Боллинджера)
* void main
Старый стандарт ISO C (ISO / IEC 9899: 1999) гласил:
[main] должен быть определен
- с типом возврата
int
и - без параметров […] или
- с два параметра […] или эквивалентный; или
- другим способом, определяемым реализацией.
§ 5.1.2.2.1 ¶ 1 стандарта C
Если тип возврата не совместим с int
, статус завершения, возвращаемый в среду хоста, не указывается.
§ 5.1. 2.2.3 ¶ 1
, который указывает, что разрешение форм, которые не возвращали int
, было преднамеренным.
Многие руководства для компиляторов (например, Watcom C / C ++, IBM VisualAge C / C ++, Microsoft Visual C / C ++) указали, что main
может иметь тип возврата void
, поэтому программа с void main()
была соответствующей программой.
Долгое время было написано много кода с возвратом тип void
. gcc
(вероятно) считает важным совместимость с унаследованным кодом и допускает void main()
, но в этом случае:
- выдает предупреждение (
warning: return type of ‘main’ is not ‘int’
); - возвращаемое значение программы не определено.
Ссылки:
* int main
int main() {}
Это не определено в C89 / 90 и хорошо определено в следующих версиях (где он возвращает 0
).
* фактическое значение
На x86 регистр EAX
обычно используется для возвращаемых значений. Таким образом,
int main() {}
компилируется в нечто вроде:
main:
push rbp
mov rbp, rsp
mov eax, 0
pop rbp
ret
Для
void main() {}
самое простое действие - удаление mov eax, 0
:
main:
push rbp
mov rbp, rsp
nop
pop rbp
ret
Если вы добавите оператор printf
:
#include <stdio.h>
void main()
{
printf("1234");
}
, вы получите:
.LC0:
.string "1234"
main:
push rbp
mov rbp, rsp
mov edi, OFFSET FLAT:.LC0
mov eax, 0
call printf
pop rbp
ret
Вызов printf
изменяет регистр EAX
(возвращает количество символов записывается в поток, и EAX
используется для возвращаемого значения).