生活随笔
收集整理的這篇文章主要介紹了
C和汇编---数组
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
0x01 初始化數組
1、沒有初始化數組
#include
"stdio.h"
int
main(void
)
{int data
[4];for (int i
=0;i
<4;i
++){printf("%d\t",data
[i
]);}return 0;
}
不同系統,輸出結果可能不一樣:
反匯編:
4: int data
[4];
5: for (int i
=0;i
<4;i
++)
00401028 C7
45 EC
00 00 00 00 mov dword ptr
[ebp
-14h
],0
0040102F EB
09 jmp main
+2Ah
(0040103a
)
00401031 8B
45 EC mov eax
,dword ptr
[ebp
-14h
]
00401034 83 C0
01 add eax
,1
00401037 89 45 EC mov dword ptr
[ebp
-14h
],eax
0040103A
83 7D EC
04 cmp dword ptr
[ebp
-14h
],4
0040103E
7D
17 jge main
+47h
(00401057)
6: {
7: printf("%d\t",data
[i
]);
00401040 8B
4D EC mov ecx
,dword ptr
[ebp
-14h
]
00401043 8B
54 8D F0 mov edx
,dword ptr
[ebp
+ecx
*4-10h
]
00401047 52 push edx
00401048 68 1C
20 42 00 push offset string
"%d\t" (0042201c
)
0040104D E8
3E
00 00 00 call printf
(00401090)
00401052 83 C4
08 add esp
,8
8: }
00401055 EB DA jmp main
+21h
(00401031)
9:
10: return 0;
00401057 33 C0 xor eax
,eax
11: }
我們可以看到int data[4];沒有生成機器碼,說明cpu到這里不會干任何事情。從上面的輸出結果可以得出,定義一個數組,會給這個數組分配內存空間,如果沒有初始化,數組的內容是相應分配空間的內容,這里我們稱之為垃圾值
2、部分初始化
#include
"stdio.h"
int
main(void
)
{int data
[4]={1,2};for (int i
=0;i
<4;i
++){printf("%d\t",data
[i
]);}return 0;
}
結果:
反匯編:
4: int data
[4]={1,2};
00401028 C7
45 F0
01 00 00 00 mov dword ptr
[ebp
-10h
],1
0040102F C7
45 F4
02 00 00 00 mov dword ptr
[ebp
-0Ch
],2
00401036 33 C0 xor eax
,eax
00401038 89 45 F8 mov dword ptr
[ebp
-8],eax
0040103B
89 45 FC mov dword ptr
[ebp
-4],eax
5: for (int i
=0;i
<4;i
++)
0040103E C7
45 EC
00 00 00 00 mov dword ptr
[ebp
-14h
],0
00401045 EB
09 jmp main
+40h
(00401050)
00401047 8B
4D EC mov ecx
,dword ptr
[ebp
-14h
]
0040104A
83 C1
01 add ecx
,1
0040104D
89 4D EC mov dword ptr
[ebp
-14h
],ecx
00401050 83 7D EC
04 cmp dword ptr
[ebp
-14h
],4
00401054 7D
17 jge main
+5Dh
(0040106d
)
6: {
7: printf("%d\t",data
[i
]);
00401056 8B
55 EC mov edx
,dword ptr
[ebp
-14h
]
00401059 8B
44 95 F0 mov eax
,dword ptr
[ebp
+edx
*4-10h
]
0040105D
50 push eax
0040105E
68 1C
20 42 00 push offset string
"%d\t" (0042201c
)
00401063 E8
28 00 00 00 call printf
(00401090)
00401068 83 C4
08 add esp
,8
8: }
0040106B EB DA jmp main
+37h
(00401047)
9:
10: return 0;
0040106D
33 C0 xor eax
,eax
11: }
從下面這段代碼可以看出,部分初始化,編譯器會給數組分配連續的空間,將有值的部分賦值到相應的內存,沒有初始化的,復制為0,這就是為什么上面的輸出結果為什么后面沒有賦值的是0
4: int data
[4]={1,2};
00401028 C7
45 F0
01 00 00 00 mov dword ptr
[ebp
-10h
],1
0040102F C7
45 F4
02 00 00 00 mov dword ptr
[ebp
-0Ch
],2
00401036 33 C0 xor eax
,eax
00401038 89 45 F8 mov dword ptr
[ebp
-8],eax
0040103B
89 45 FC mov dword ptr
[ebp
-4],eax
3、全部初始化數組
#include
"stdio.h"
int
main(void
)
{int data
[4]={1,2,3,4};for (int i
=0;i
<4;i
++){printf("%d\t",data
[i
]);}return 0;
}
4: int data
[4]={1,2,3,4};
00401028 C7
45 F0
01 00 00 00 mov dword ptr
[ebp
-10h
],1
0040102F C7
45 F4
02 00 00 00 mov dword ptr
[ebp
-0Ch
],2
00401036 C7
45 F8
03 00 00 00 mov dword ptr
[ebp
-8],3
0040103D C7
45 FC
04 00 00 00 mov dword ptr
[ebp
-4],4
5: for (int i
=0;i
<4;i
++)
00401044 C7
45 EC
00 00 00 00 mov dword ptr
[ebp
-14h
],0
0040104B EB
09 jmp main
+46h
(00401056)
0040104D
8B
45 EC mov eax
,dword ptr
[ebp
-14h
]
00401050 83 C0
01 add eax
,1
00401053 89 45 EC mov dword ptr
[ebp
-14h
],eax
00401056 83 7D EC
04 cmp dword ptr
[ebp
-14h
],4
0040105A
7D
17 jge main
+63h
(00401073)
6: {
7: printf("%d\t",data
[i
]);
0040105C
8B
4D EC mov ecx
,dword ptr
[ebp
-14h
]
0040105F
8B
54 8D F0 mov edx
,dword ptr
[ebp
+ecx
*4-10h
]
00401063 52 push edx
00401064 68 1C
20 42 00 push offset string
"%d\t" (0042201c
)
00401069 E8
22 00 00 00 call printf
(00401090)
0040106E
83 C4
08 add esp
,8
8: }
00401071 EB DA jmp main
+3Dh
(0040104d
)
9:
10: return 0;
00401073 33 C0 xor eax
,eax
可以看出如果一開始全部初始化數組,會立即分配連續空間給數組,每個空間賦值為數組相應位置的值
4、總結
不初始化數組,數組元素存儲的是垃圾值;部分初始化數組,剩余的被初始化為0;全部初始化,將值賦值到相應內存空間,而且數組的物理地址連續
0x02多維數組是如何分配空間的
多維數組的初始化情況和一維數組一樣,那么多維數組是如何分配空間的呢?我們以二維數組為列:
#include
"stdio.h"
int
main(void
)
{int data
[2][2]={{1,2},{3,4}};return 0;
}
反匯編:
4: int data
[2][2]={{1,2},{3,4}};
00401028 C7
45 F0
01 00 00 00 mov dword ptr
[ebp
-10h
],1
0040102F C7
45 F4
02 00 00 00 mov dword ptr
[ebp
-0Ch
],2
00401036 C7
45 F8
03 00 00 00 mov dword ptr
[ebp
-8],3
0040103D C7
45 FC
04 00 00 00 mov dword ptr
[ebp
-4],4
5:
6: return 0;
00401044 33 C0 xor eax
,eax
7: }
我們可以看出先將1,2存到連續空間。再將3,4存到接下來的空間(數組的內存空間是連續的),所以這就是為什么上課時老師說把二維數組當成一維數組來理解了,data[0]和data[1]分別為一個一維數組,二維數組按照從左到右,從上到下存儲,地址連續
- int data[2][2]:data是一個兩個元素的數組,每個元素內含2個int類型元素的數組
- data的首地址是data[0],data[0]是一個內含2個int類型值的數組,所以data[1]也是這樣
0x03 指針和數組
1、一維數組
我們知道數組名是數組的首地址,可為什么呢?接下來我們分析
#include
"stdio.h"
int
main(void
)
{int data
[4]={1,3,7,4};int
*p
;p
=data
;printf("%d\n",p
[0]);printf("%d\n",*p
+2);printf("%d\n",*(p
+2));return 0;
}
結果:
反匯編:
4: int data
[4]={1,3,7,4};
0040D738 C7
45 F0
01 00 00 00 mov dword ptr
[ebp
-10h
],1
0040D73F C7
45 F4
03 00 00 00 mov dword ptr
[ebp
-0Ch
],3
0040D746 C7
45 F8
07 00 00 00 mov dword ptr
[ebp
-8],7
0040D74D C7
45 FC
04 00 00 00 mov dword ptr
[ebp
-4],4
5: int
*p
;
6: p
=data
;
0040D754
8D
45 F0 lea eax
,[ebp
-10h
]
0040D757
89 45 EC mov dword ptr
[ebp
-14h
],eax
7: printf("%d\n",p
[0]);
0040D75A
8B
4D EC mov ecx
,dword ptr
[ebp
-14h
]
0040D75D
8B
11 mov edx
,dword ptr
[ecx
]
0040D75F
52 push edx
0040D760
68 1C
20 42 00 push offset string
"%d\t" (0042201c
)
0040D765 E8
26 39 FF FF call printf
(00401090)
0040D76A
83 C4
08 add esp
,8
8: printf("%d\n",*p
+2);
0040D76D
8B
45 EC mov eax
,dword ptr
[ebp
-14h
]
0040D770
8B
08 mov ecx
,dword ptr
[eax
]
0040D772
83 C1
02 add ecx
,2
0040D775
51 push ecx
0040D776
68 1C
20 42 00 push offset string
"%d\t" (0042201c
)
0040D77B E8
10 39 FF FF call printf
(00401090)
0040D780
83 C4
08 add esp
,8
9: printf("%d\n",*(p
+2));
0040D783
8B
55 EC mov edx
,dword ptr
[ebp
-14h
]
0040D786
8B
42 08 mov eax
,dword ptr
[edx
+8]
0040D789
50 push eax
0040D78A
68 1C
20 42 00 push offset string
"%d\t" (0042201c
)
0040D78F E8 FC
38 FF FF call printf
(00401090)
0040D794
83 C4
08 add esp
,8
10: return 0;
0040D797
33 C0 xor eax
,eax
從數組初始化我們看不出來data是數組的首地址嗎,但可以從p=data看出
6: p
=data
;
0040D754
8D
45 F0 lea eax
,[ebp
-10h
]
0040D757
89 45 EC mov dword ptr
[ebp
-14h
],eax
把 [ebp-10h]偏移地址給eax,eax再賦值給dword ptr [ebp-14h],ebp-10h是第一個元素1的地址,所以data是數組首地址,我們將data值賦值給p,此時p和data可以看成等同的,p[0]就是data[0]。
- 指針加1是增加一個存儲單元,比如說*(p+2),p+2就是增加兩個存儲單元(int是4byte),所以輸出*(p+2)是7
- 輸出p+2,此時p是1,加2是3所以會輸出3
2、多維數組
以二維數組為例
#include
"stdio.h"
int
main(void
)
{int data
[3][3]={{1,2,3},{4,5,6},{7,8,9}};int
(* p
)[3]; p
=data
;printf("%d\n",p
);printf("%d\n",*p
);printf("%d\n",*(p
+1));printf("%d\n",**p
);printf("%d\n",p
[0]);printf("%d\n",*p
[0]);return 0;
}
反匯編:
4: int data
[3][3]={{1,2,3},{4,5,6},{7,8,9}};
0040D738 C7
45 DC
01 00 00 00 mov dword ptr
[ebp
-24h
],1
0040D73F C7
45 E0
02 00 00 00 mov dword ptr
[ebp
-20h
],2
0040D746 C7
45 E4
03 00 00 00 mov dword ptr
[ebp
-1Ch
],3
0040D74D C7
45 E8
04 00 00 00 mov dword ptr
[ebp
-18h
],4
0040D754 C7
45 EC
05 00 00 00 mov dword ptr
[ebp
-14h
],5
0040D75B C7
45 F0
06 00 00 00 mov dword ptr
[ebp
-10h
],6
0040D762 C7
45 F4
07 00 00 00 mov dword ptr
[ebp
-0Ch
],7
0040D769 C7
45 F8
08 00 00 00 mov dword ptr
[ebp
-8],8
0040D770 C7
45 FC
09 00 00 00 mov dword ptr
[ebp
-4],9
5: int
(* p
)[3];
6: p
=data
;
0040D777
8D
45 DC lea eax
,[ebp
-24h
]
0040D77A
89 45 D8 mov dword ptr
[ebp
-28h
],eax
7: printf("%d\n",p
);
0040D77D
8B
4D D8 mov ecx
,dword ptr
[ebp
-28h
]
0040D780
51 push ecx
0040D781
68 1C
20 42 00 push offset string
"%d\t" (0042201c
)
0040D786 E8
05 39 FF FF call printf
(00401090)
0040D78B
83 C4
08 add esp
,8
8: printf("%d\n",*p
);
0040D78E
8B
55 D8 mov edx
,dword ptr
[ebp
-28h
]
0040D791
52 push edx
0040D792
68 1C
20 42 00 push offset string
"%d\t" (0042201c
)
0040D797 E8 F4
38 FF FF call printf
(00401090)
0040D79C
83 C4
08 add esp
,8
9: printf("%d\n",*(p
+1));
0040D79F
8B
45 D8 mov eax
,dword ptr
[ebp
-28h
]
0040D7A2
83 C0
0C add eax
,0Ch
0040D7A5
50 push eax
0040D7A6
68 1C
20 42 00 push offset string
"%d\t" (0042201c
)
0040D7AB E8 E0
38 FF FF call printf
(00401090)
0040D7B0
83 C4
08 add esp
,8
10: printf("%d\n",**p
);
0040D7B3
8B
4D D8 mov ecx
,dword ptr
[ebp
-28h
]
0040D7B6
8B
11 mov edx
,dword ptr
[ecx
]
0040D7B8
52 push edx
0040D7B9
68 1C
20 42 00 push offset string
"%d\t" (0042201c
)
0040D7BE E8 CD
38 FF FF call printf
(00401090)
0040D7C3
83 C4
08 add esp
,8
11: printf("%d\n",p
[0]);
0040D7C6
8B
45 D8 mov eax
,dword ptr
[ebp
-28h
]
0040D7C9
50 push eax
0040D7CA
68 1C
20 42 00 push offset string
"%d\t" (0042201c
)
0040D7CF E8 BC
38 FF FF call printf
(00401090)
0040D7D4
83 C4
08 add esp
,8
12: printf("%d\n",*p
[0]);
0040D7D7
8B
4D D8 mov ecx
,dword ptr
[ebp
-28h
]
0040D7DA
8B
11 mov edx
,dword ptr
[ecx
]
0040D7DC
52 push edx
0040D7DD
68 1C
20 42 00 push offset string
"%d\t" (0042201c
)
0040D7E2 E8 A9
38 FF FF call printf
(00401090)
0040D7E7
83 C4
08 add esp
,8
13: return 0;
0040D7EA
33 C0 xor eax
,eax
- 從p=data;, printf("%d\n",p[0]);,printf("%d\n",**p);的反匯編看出,數組名和數組名[0]是首元素的地址,printf("%d\n",*p);,數組名像是指向數組名[0]的指針,這就是為什么二維數組的元素可以看成一維數組
- printf("%d\n",*(p+1));從反匯編里看出,加了0ch,就是加12,并不是加4,二維數組的元素是一維數組,一維數組占3個int類型,所以12,所以*(p+1)指向data[1]
- 函數里使用二維數組:比如說int sum(int data[][3]),第一個[]表明data是一個指針
總結
以上是生活随笔為你收集整理的C和汇编---数组的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。