что означает код выхода программы с пустым void main ()? - PullRequest
1 голос
/ 04 апреля 2020

Я сделал простую C программу с пустым main, как указано ниже, и скомпилировал ее с g cc

void main(){
}

при выполнении, он возвращает код выхода как 25, и если я добавлю оператор printf, после включения stdio.h, возвращает код завершения 5

что означает здесь 25 и 5 и почему он возвращается любым кодом, который выполняется до или после main ()? Код выхода равен нулю, если я использую int main () и не помещаю инструкцию возврата.

Ответы [ 2 ]

5 голосов
/ 04 апреля 2020

в чем здесь значение 25 и 5

Спецификации языка C не определяют поведение для программы, для которой main() объявлено как возвращающее void. Реализации, которые, тем не менее, принимают такой код, могут определять или не определять его поведение. В общем смысле, тогда нет статусов выхода имеют какое-либо значение или значение для программы с void main().

Очевидно, G CC, в частности, действительно принимает код, но я не найти определения его поведения среди документально подтвержденных C *1013* расширений G CC, поэтому ни в одном конкретном случае наблюдаемые вами состояния выхода не имеют никакого значения.

и почему он возвращается любым кодом, который выполняется до или после main ()?

Нет особой причины. Поведение не определено.

Код выхода равен нулю, если я использую int main () и не помещаю инструкцию возврата.

Этот случай хорошо определен. C указывает, что если выполнение достигает конца начального вызова к main() (предположительно объявленному с одной из двух C -стандартных подписей, обе из которых возвращают int), то поведение будет таким, как если бы exit(0) были названы. Это особый случай. В противном случае поведение не определено, если выполнение достигает закрывающей скобки функции, не являющейся void, и ее вызывающая сторона делает что-либо с возвращаемым значением.

3 голосов
/ 04 апреля 2020

(Добавление к ответу Джона Боллинджера)

* 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 используется для возвращаемого значения).

...