Здравствуйте!Занимаюсь по курсам на intuit.ru Возникли вопросы уже на после первого занятия. (со второго раза сдал на 83%)
Итак. Там был вопрос, который поставил меня в тупик. Привожу по памяти:
"Дана программа:
main(){
printf("Hello, world!\n");
}Что произойдёт при компиляции:
1) программа успешко скомпилируется и запустится
2) программа не скомпилируется из-за синтаксической ошибки
3) программа успешно скомпилируется но код возврата будет не определён
4) программа не скомпилируется, потому что у main() отсутствует аргумент (или возвращаемое значение? точно не помню :))
"Так вот. Вроде вопрос-то простой. Но вот что я заметил:
[c0der@semushin ~]$ cat test1.c
main(){}
[c0der@semushin ~]$ cat test2.c
main(){printf("hello\n");}
[c0der@semushin ~]$ cat test3.c
main(){printf("hello world!\n");}
[c0der@semushin ~]$ gcc test1.c -o test1
[c0der@semushin ~]$ gcc test2.c -o test2
[c0der@semushin ~]$ gcc test3.c -o test3
[c0der@semushin ~]$ ./test1
[c16der@semushin ~]$ ./test2
hello
[c6der@semushin ~]$ ./test3
hello world!Т.е. в трёх разных случаях код возврата разный. Т.е. получается, что он и правда без return будет не определён ? Он от чего-нибудь зависит ? Почему не возвращается ноль по умолчанию?
Спасибо заранее за разъяснения.
>Спасибо заранее за разъяснения.
По завершению main если return не указан - вызывается функция libc - exit и берет со стека этот самый код возврата, а что это будет - а х.з., что оказалось по адресу аргумента, то и будет.
>>Спасибо заранее за разъяснения.
>По завершению main если return не указан - вызывается функция libc -
>exit и берет со стека этот самый код возврата, а что
>это будет - а х.з., что оказалось по адресу аргумента, то
>и будет.нет, не совсем. если return не указан, то его подставляет gcc, в main, точно так же, как и в любой другой функции. main, по идее должна возвращать в %eax, код возврата, вопрос в том какое значение %eax будет перед выполнением инструкции ret.
в этом примере, скорее всего, %eax == значению, которое возвращает printf. То есть просто это так и есть, другое дело, что никакой гарантии, что так будет всегда никто не даст.
результат `gcc -S tmp.c`:
main:
pushl %ebp
movl %esp, %ebp
subl $8, %esp
andl $-16, %esp
movl $0, %eax
addl $15, %eax
addl $15, %eax
shrl $4, %eax
sall $4, %eax
subl %eax, %esp
movl $.LC0, (%esp)
call printf
leave
ret
между call printf и ret нету ничего, что могло бы изменить %eax, вот и результат.
>"Дана программа:
>main(){
> printf("Hello, world!\n");
>}
>
>Что произойдёт при компиляции:
>
>1) программа успешко скомпилируется и запустится
>2) программа не скомпилируется из-за синтаксической ошибки
>3) программа успешно скомпилируется но код возврата будет не определён
>4) программа не скомпилируется, потому что у main() отсутствует аргумент
>(или возвращаемое значение? точно не помню :))Оно со стека должно ухватить код возврата printf()'а.
Но стандарт языка сие, по-моему, не гарантирует.
А printf() возвращает число выведенных символов.
Так что код возврата будет 14.>Т.е. в трёх разных случаях код возврата разный.
По Вашим примерам не видно, где берется код возврата.
Но он действительно будет разный, так как длины строк - разные.
>Т.е. в трёх разных случаях код возврата разный. Т.е. получается, что он
>и правда без return будет не определён ? Он от чего-нибудь
>зависит ? Почему не возвращается ноль по умолчанию?"По умолчанию" в C ничего не бывает - всё ручками. В данном случае возвращается мусор из стека.
При всех включенных проверках программа компилироваться не должна - printf не определён.