生活随笔
收集整理的這篇文章主要介紹了
                                
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和汇编---数组的全部內容,希望文章能夠幫你解決所遇到的問題。
                            
                            
                                如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。