2016-10-18 1 views
1

«Printf» возвращает количество символов, на самом деле печатных, так что я имел:

#include<stdio.h> 
int main() 
{ 
    printf("1"); 
    printf("55555"); 
    printf("10________"); 
    printf("13___________"); 
    printf("18________________"); 
    printf("28__________________________"); 
} 

Эта программа будет выводить

15555510________13___________18________________28__________________________ 

Тогда я попытался его отладки в GDB и проверить возвращаемое значение БГД :

(gdb) b main 
Breakpoint 1 at 0x804844c: file testp.c, line 4. 
(gdb) r 
Starting program: /home/a/cpp/a.out 

Breakpoint 1, main() at testp.c:4 
4  printf("1"); 
(gdb) n    # will return "1" to $eax 
5  printf("55555"); 
(gdb) p $eax   # I expect it will print "1" here, wrong! 
$1 = 49 
(gdb) n 
6  printf("10________"); 
(gdb) p $eax   # I expect it will print "5" here, right! 
$2 = 5 
(gdb) n 
7  printf("13____________"); 
(gdb) p $eax   # I expect it will print "10" here, right! 
$3 = 10 

Как вы могли видеть, когда первый printf запущен, значение $ eax не является моим ожиданием. Более поздние значения кажутся правильными. Почему это? Почему первый printf не возвращает «1» в $ eax? Я полагаю, что c style ABI сохраняет возвращаемое значение в $ eax, правильно?

Благодаря

ответ

1

НКУ могут заменить вызовы на printf с более эффективным кодом, такие как вызовы puts или putchar, в некоторых случаях, когда оптимизация не изменит документированное поведение функций (например, когда вывод не требует какого-либо форматирования, и вы не используете возвращаемое значение). Вот что здесь происходит. Вы видите 49 in% eax, потому что putchar возвращает либо символ, который был выведен, либо EOF.

(gdb) disass /m main 
Dump of assembler code for function main: 
3 { 
    0x000000000040057d <+0>: push %rbp 
    0x000000000040057e <+1>: mov %rsp,%rbp 

4  printf("1"); 
    0x0000000000400581 <+4>: mov $0x31,%edi 
    0x0000000000400586 <+9>: callq 0x400450 <[email protected]> 

5  printf("55555"); 
    0x000000000040058b <+14>: mov $0x400664,%edi 
    0x0000000000400590 <+19>: mov $0x0,%eax 
    0x0000000000400595 <+24>: callq 0x400460 <[email protected]> 

Чтобы получить GCC генерировать вызовы на printf все время, вы можете использовать опцию -fno-builtin-printf.

+0

Спасибо, -fno-builtin-printf работает для меня. Я был просто смущен, я не использовал опцию «-O» или не делал оптимизацию, почему gcc все еще делает некоторую оптимизацию? Как вручную отключить его полностью? – Troskyvs

+0

Даже с '-O0', gcc по-прежнему будет заменять эквивалентный более эффективный код для стандартных функций, таких как' printf' и 'strcpy', если вы не дадите ему опцию' -fno-builtin' или 'no-builtin-nameoffunc'. –

Смежные вопросы