C - что такое возвращаемое значение точки с запятой? - PullRequest
3 голосов
/ 15 января 2010

Мне просто интересно узнать следующий пример

#include<stdio.h>
int test();
int test(){
     //    int a = 5;
     //    int b = a+1;
     return ;
}
int main(){
     printf("%u\n",test());
     return 0;
}

Я скомпилировал его с помощью 'gcc -Wall -o точка с запятой точка с запятой.c', чтобы создать исполняемый файл и 'gcc -Wall -S semicolon.c' дляполучить код ассемблера:

    .file   "semicolon.c"
    .text
.globl test
    .type   test, @function
test:
    pushl   %ebp
    movl    %esp, %ebp
    subl    $4, %esp
    leave
    ret
    .size   test, .-test
    .section        .rodata
 .LC0:
    .string "%u\n"
    .text
 .globl main
    .type   main, @function
 main:
    leal    4(%esp), %ecx
    andl    $-16, %esp
    pushl   -4(%ecx)
    pushl   %ebp
    movl    %esp, %ebp
    pushl   %ecx
    subl    $20, %esp
    call    test
    movl    %eax, 4(%esp)
    movl    $.LC0, (%esp)
    call    printf
    movl    $0, %eax
    addl    $20, %esp
    popl    %ecx
    popl    %ebp
    leal    -4(%ecx), %esp
    ret
    .size   main, .-main
    .ident  "GCC: (Ubuntu 4.3.3-5ubuntu4) 4.3.3"
    .section        .note.GNU-stack,"",@progbits

, так как я не такой профессионал по ассемблеру, я знаю только, что printf печатает то, что находится в eax, но я не до конца понимаю, что 'movl% eax, 4 (% esp)'означает, что я предполагаю, что заполняет eax перед вызовом test, но какое тогда значение?что означает 4 (% esp) и что означает значение esp?

, если я раскомментирую строки в test () printf print 6 - который написан на eax ^^

Ответы [ 4 ]

9 голосов
/ 15 января 2010

Ваш ассемблер аннотирован:

test:
    pushl   %ebp        # Save the frame pointer
    movl    %esp, %ebp  # Get the new frame pointer.
    subl    $4, %esp    # Allocate some local space on the stack.
    leave               # Restore the old frame pointer/stack
    ret

Обратите внимание, что ничто в тесте не касается eax.

.size   test, .-test
.section        .rodata
 .LC0:
.string "%u\n"
.text
 .globl main
.type   main, @function
main:
leal    4(%esp), %ecx      # Point past the return address.
andl    $-16, %esp         # Align the stack.
pushl   -4(%ecx)           # Push the return address.
pushl   %ebp               # Save the frame pointer
movl    %esp, %ebp         # Get the new frame pointer.
pushl   %ecx               # save the old top of stack.
subl    $20, %esp          # Allocate some local space (for printf parameters and ?).
call    test               # Call test.

Обратите внимание, что на данный момент ничто не изменило eax. Все, что вошло в главное, все еще здесь.

movl    %eax, 4(%esp)      # Save eax as a printf argument.
movl    $.LC0, (%esp)      # Send the format string.
call    printf             # Duh.
movl    $0, %eax           # Return zero from main.
addl    $20, %esp          # Deallocate local space.
popl    %ecx               # Restore the old top of stack.
popl    %ebp               # And the old frame pointer.
leal    -4(%ecx), %esp     # Fix the stack pointer,
ret

Итак, то, что распечатывается, - это то, что пришло на главную. Как уже отмечали другие, он не определен: это зависит от того, что код запуска (или ОС) сделал для eax.

7 голосов
/ 15 января 2010

Точка с запятой не имеет возвращаемого значения, у вас есть «пустое возвращение», подобное тому, которое использовалось для возврата из пустых функций - поэтому функция ничего не возвращает.

Это фактически вызывает предупреждение при компиляции:

warning: `return' with no value, in function returning non-void

И я не вижу ничего помещенного в eax до вызова test.

Около 4 (% esp), это означает получение значения из указателя стека (esp) + 4. Т.е. слово, предшествующее последнему в стеке.

2 голосов
/ 15 января 2010

Возвращаемое значение функции int передается в регистр EAX. Тестовая функция не устанавливает регистр EAX, поскольку возвращаемое значение не задано. Поэтому результат не определен.

0 голосов
/ 15 января 2010

Точка с запятой действительно не имеет значения.

Я думаю, что правильный ответ таков: return <nothing> для функции int является ошибкой или, по крайней мере, имеет неопределенное поведение. Вот почему компиляция этого с -Wall приводит к

semi.c: In function ‘test’:
semi.c:6: warning: ‘return’ with no value, in function returning non-void

Что касается того, что содержит %4,esp ... это место в стеке, где ничего не было (намеренно) сохранено, так что оно, скорее всего, вернет любой мусор, найденный в этом месте. Это может быть последнее выражение, вычисленное для переменных в функции (как в вашем примере) или что-то совершенно другое. Это то, что "неопределенный" это все о. :)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...