編譯環境gcc4.4.1
如下代碼
int a = 4;
a += (a++);
printf("%d\n",a);

a = 4;
a += (++a) ;
printf("%d\n",a);

a = 4;
(++a) += a;
printf("%d\n",a);

a = 4;
(a++) += a;//a++不能作為左值參加運算。
printf("%d\n",a);

a = 4;
(++a) += (a++);
printf("%d\n",a);
打印的值為9,10,10,11。匯編代碼如下:
# a += (a++);
00401326 movl $0x4,0x1c(%esp)
0040132E mov 0x1c(%esp),%eax
00401332 add %eax,%eax
00401334 mov %eax,0x1c(%esp)
00401338 incl 0x1c(%esp)
0040133C mov 0x1c(%esp),%eax
00401340 mov %eax,0x4(%esp)
00401344 movl $0x46f024,(%esp)
0040134B call 0x41c750 <printf>
# a += (++a) ;
00401350 movl $0x4,0x1c(%esp)
00401358 incl 0x1c(%esp)
0040135C mov 0x1c(%esp),%eax
00401360 add %eax,%eax
00401362 mov %eax,0x1c(%esp)
00401366 mov 0x1c(%esp),%eax
0040136A mov %eax,0x4(%esp)
0040136E movl $0x46f024,(%esp)
00401375 call 0x41c750 <printf>
# (++a) += a;
0040137A movl $0x4,0x1c(%esp)
00401382 incl 0x1c(%esp)
00401386 mov 0x1c(%esp),%eax
0040138A add %eax,%eax
0040138C mov %eax,0x1c(%esp)
00401390 mov 0x1c(%esp),%eax
00401394 mov %eax,0x4(%esp)
00401398 movl $0x46f024,(%esp)
0040139F call 0x41c750 <printf>
#(++a) += (a++);
004013A4 movl $0x4,0x1c(%esp)
004013AC incl 0x1c(%esp)
004013B0 mov 0x1c(%esp),%eax
004013B4 add %eax,%eax
004013B6 mov %eax,0x1c(%esp)
004013BA incl 0x1c(%esp)
004013BE mov 0x1c(%esp),%eax
004013C2 mov %eax,0x4(%esp)
004013C6 movl $0x46f024,(%esp)
004013CD call 0x41c750 <printf>
可以看出,在運算過程中,++a優先級> += > a++
1)先運算a+a,然后再自增a
2),3)先運算++a,然后再a+a
4)先運算++a,然后a+a,然后a++
定義如下一個struct
struct T
{
int a;
int b[0];
int c;
};
打印各個成員的地址和大小,結果如下:
編譯環境Code::Blocks 10.05
struct T t;
printf("%p:%d\n",&(t.a),sizeof(t.a));
printf("%p:%d\n",&(t.b),sizeof(t.b));
printf("%p:%d\n",&(t.c),sizeof(t.c));
0022FF38:4
0022FF3C:0
0022FF3C:4
可見定義的空數組,是不占任何空間的。其返回的內存地址是下一個可分配的地址。
如果在返回值為int的函數里,漏掉return,會發生什么情況?
編譯工具:Code::Blocks 10.05,代碼如下所示
#include <cstdio>
int f()
{
}
int main ()
{
printf("%d ",f());
printf("%d ",f());
printf("%d ",f());
return 0;
}
編譯時,提示
In function 'int f()':|
warning: no return statement in function returning non-void|
但是能編譯
Debug版本下結果如下:
1 2 2
Release版本下結果
0 0 0
下面分析一下為什么為發生這種情況:
從code:: blocks里面看到的 函數f的匯編代碼
00401318 push %ebp
00401319 mov %esp,%ebp //正確的似乎是 mov %ebp %esp
0040131B leave
0040131C ret
如果函數f()如下定義
int f()
{
return 100;
}
則匯編代碼是
00401318 push %ebp
00401319 mov %esp,%ebp
0040131B mov $0x64,%eax
00401320 leave
00401321 ret
接下來我們看一下整個main函數的匯編代碼
00401322 push %ebp
00401323 mov %esp,%ebp
00401325 and $0xfffffff0,%esp
00401328 sub $0x10,%esp
0040132B call 0x401770 <__main>
00401330 call 0x401318 <f()>
00401335 mov %eax,0x4(%esp)
00401339 movl $0x403024,(%esp)
00401340 call 0x4019ac <printf>
00401345 call 0x401318 <f()>
0040134A mov %eax,0x4(%esp)//將返回值傳遞給%esp+0x04
0040134E movl $0x403024,(%esp)
00401355 call 0x4019ac <printf>
0040135A call 0x401318 <f()>
0040135F mov %eax,0x4(%esp)
00401363 movl $0x403024,(%esp)
0040136A call 0x4019ac <printf>
0040136F mov $0x0,%eax
00401374 leave
00401375 ret
從中我們可以看出,函數f()是將返回值通過EAX寄存器中,傳遞給調用它的代碼。
如過我們漏掉了return intVal語句,在Debug模式下可能會導致,調用f()的代碼得到的是上次的其他函數被調用的返回值。
在進入main之后EAX通常會被初始化為0x01.所以第一個f() 返回值為1.
printf 打印了“1 ”兩個字符之后,返回值為2,所以第二個f()返回值為2。
printf 打印了“2 ”兩個字符之后,返回值為2,所以第三個f()返回值為2。
在Release版本下,函數f()被優化,printf直接打印數字0。
401320: push %ebp
401321: mov %esp,%ebp
401323: and $0xfffffff0,%esp
401326: sub $0x10,%esp
401329: call 0x401760
40132e: movl $0x0,0x4(%esp)
401335:
401336: movl $0x403024,(%esp)
40133d: call 0x40199c
401342: movl $0x0,0x4(%esp)
401349:
40134a: movl $0x403024,(%esp)
401351: call 0x40199c
401356: movl $0x0,0x4(%esp)
40135d:
40135e: movl $0x403024,(%esp)
401365: call 0x40199c
40136a: xor %eax,%eax
40136c: leave
40136d: ret