新聞中心

        C語言數(shù)組分析

        作者: 時(shí)間:2016-12-01 來源:網(wǎng)絡(luò) 收藏
        以前學(xué)習(xí)C語言的時(shí)候覺得數(shù)組和指針結(jié)合在一起的時(shí)候真的是地獄,很容易就搞混淆了,最近看了C語言深度解剖有了一點(diǎn)理解,好好的總結(jié)一下吧。其中很多的知識(shí)都是因?yàn)槲覀冊(cè)趯W(xué)習(xí)的過程中沒有仔細(xì)的去分析導(dǎo)致的。同時(shí)我體會(huì)到了我們?cè)趯懘a的過程中應(yīng)該更多的注重代碼的調(diào)試,而不是換新的代碼,只有不斷的調(diào)試才能知道其中問題所在。
        數(shù)組和指針之間本來沒有什么關(guān)系,數(shù)組就是數(shù)組,指針就是指針,之間并沒有關(guān)系,只是因?yàn)槟承┫嗨铺匦允沟梦覀冊(cè)诜治龅倪^程中存在較大的迷惑。
        數(shù)組就是一個(gè)連續(xù)存儲(chǔ)空間的存儲(chǔ)的數(shù)值。指針就是指針,指針變量所在內(nèi)存中存儲(chǔ)的值都是地址。
        C 語言中數(shù)組的大小必須是一個(gè)常數(shù),但是不能認(rèn)為采用const限定的變量就能作為數(shù)組大小的值,在C語言中const并不是定義一個(gè)常數(shù),只是定義了一個(gè)只讀類型的數(shù)據(jù),并不是常數(shù)。在C語言中通常采用:
        #define N 5
        int Array[N];
        const int M = 5;
        int Array[M];//這是一種錯(cuò)誤的定義方式,注意const并不是定義常量,但是C++中可以這樣定義。
        在一維數(shù)組中使用下標(biāo)來訪問數(shù)組,Array是整個(gè)分配存儲(chǔ)空間的名字,單個(gè)的存儲(chǔ)空間并沒有名字。這個(gè)存儲(chǔ)空間存儲(chǔ)的值為數(shù)組的元素,主要是 Array[0],Array[1],...,Array[N-1],數(shù)組元素并沒有名字。我們對(duì)數(shù)組的訪問主要是采用下標(biāo)的方式進(jìn)行訪問。Array與這塊存儲(chǔ)空間已經(jīng)密切的關(guān)聯(lián)起來,不能改變。但是需要主要的是Array作為右值時(shí),表示的是該數(shù)組首個(gè)元素(Array[0])的地址,而不是代表整個(gè)數(shù)組的地址起始地址,雖然兩個(gè)起始地址是相同的,但是需要理清其中的概念。整個(gè)數(shù)組的起始地址可以通過對(duì)這塊存儲(chǔ)區(qū)域取地址,也就是采用&a,這時(shí)得到的值才是整個(gè)數(shù)組的起始地址,雖然兩個(gè)值是相同的,但是需要搞清楚其中的道理。
        在數(shù)組中位置的變化也是非常重要的。
        int *p = NULL;
        p = Array + 1;
        是指在數(shù)組Array的首元素的首地址上增加一個(gè)元素的寬度,使得p指向Array[1]。因?yàn)锳rray表示的是數(shù)組首個(gè)元素的首地址,那么操作的最小單位就是元素,Array + 1就是訪問下一個(gè)元素。
        p = &Array + 1;
        由于&Array是表示數(shù)組的起始地址,操作的最小單位是一個(gè)數(shù)組,而不是元素,因此Array+1就是下一個(gè)數(shù)組的起始地址,也就是將p指向了Array的下一個(gè)數(shù)組,而不是元素。
        因此需要注意一維數(shù)組名在作為右值時(shí)是表示數(shù)組首個(gè)元素的首地址,并不表示整個(gè)數(shù)組的首地址。
        對(duì)于二維數(shù)組(多維數(shù)組)也存在類似的問題。
        int *p = NULL;
        #define N 5
        #define M 5
        int A[N][M];
        數(shù)組A存在5個(gè)元素,每一個(gè)元素是一個(gè)數(shù)組,每個(gè)數(shù)組中存在5個(gè)元素。數(shù)組名A表示首個(gè)元素的首地址,因此A表示A[0]的首地址,A的元素為數(shù)組,A + 1表示下一個(gè)元素(小數(shù)組)也就是A[1]的首地址;&A表示整個(gè)數(shù)組的首地址。&A+1表示下一個(gè)數(shù)組的起始地址。
        A作為右值時(shí),表示數(shù)組首元素的首地址,也就是A[0]的首地址,A[i]作為右值時(shí)是表示第i個(gè)元素(也是數(shù)組)的首元素(A[i][0])的首地址。由于A表示地址,這與指針存在很多的相似性,因此可采用指針的方式進(jìn)行訪問。具體的實(shí)現(xiàn)過程如下:
        A %%第0行的元素的首地址,不是第0行第0個(gè)元素的地址
        A[i] <---> *(A+i); %%第i行第0個(gè)元素的地址
        A[i][j] <---> *(*(A+i)+j); %%第i行第j個(gè)元素
        &A[i][j] <---> (*(A+i)+j); %%第i行第j個(gè)元素的地址
        A[i]+j <---> (*(A+i)+j); %%第i行第j個(gè)元素的地址
        &A+1 %%下一組數(shù)組的起始地址
        A+i %%第i行數(shù)組的起始地址
        在多維數(shù)組中存儲(chǔ)方式是線性的存儲(chǔ)方式,可以通過指針快速的訪問。首先A表示首元素的首地址,將指針指向這個(gè)首地址就能快速的實(shí)現(xiàn)訪問。
        為了說明這些相互關(guān)系的,采用GDB對(duì)數(shù)組進(jìn)行調(diào)試:
        int main()
        {
        int i = 0,j = 0;
        int a[5][5];
        int b[5]={4,5,7,8,9};
        for(;i < 5; ++i)
        for(;j<5;++j)
        a[i][j] = (i-j)+15;
        }
        編譯調(diào)試:
        (gdb) p a
        $1 = {{15, 14, 13, 12, 11}, {32768, 8736756, 8729060, -1073744844,
        -1073745080}, {0, -1073744928, 134518436, -1073745064, 134513340}, {
        7298965, 134518436, -1073745016, 134513785, 134513194}, {8740000, 8740000,
        8736756, 134513760, 134513408}}
        (gdb) p &a
        $2 = (int (*)[5][5]) 0xbffff314
        (gdb) p &a+1
        $3 = (int (*)[5][5]) 0xbffff378
        (gdb) p a+1
        $4 = (int (*)[5]) 0xbffff328
        (gdb) p *(a+1)
        $5 = {32768, 8736756, 8729060, -1073744844, -1073745080}
        (gdb) p *(a+1)+1
        $6 = (int *) 0xbffff32c
        (gdb) p *(*(a+1)+1)
        $7 = 8736756
        (gdb) p *a
        $8 = {15, 14, 13, 12, 11}
        (gdb) p **a
        $9 = 15
        (gdb) p **(a+1)
        $10 = 32768
        (gdb) p a[1]
        $11 = {32768, 8736756, 8729060, -1073744844, -1073745080}
        (gdb) p *a[1]
        $12 = 32768
        (gdb) p a[1]+1
        $13 = (int *) 0xbffff32c
        (gdb) p *(a[1]+1)
        $14 = 8736756
        根據(jù)$2 = (int (*)[5][5]) 0xbffff314中的[5][5]可知&a的大小是5*5的空間,剛好是一個(gè)數(shù)組的大小,說明&a表示整個(gè)數(shù)組的起始地址。(gdb) p &a+1 $3 = (int (*)[5][5]) 0xbffff378 中的[5][5]可知&a+1也是一個(gè)數(shù)組的起始地址,這也說明了&a是整個(gè)數(shù)組的初始地址。
        (gdb) p a+1,$4 = (int (*)[5]) 0xbffff328中的[5]說明a+1是元素a[1](數(shù)組5個(gè)元素)的起始地址,而不是某一個(gè)數(shù)值(二維元素)的起始地址。
        (gdb) p *a,$8 = {15, 14, 13, 12, 11},(gdb) p **a,$9 = 15,$8,$9說明a表示的是元素a[0](一個(gè)小數(shù)組)的起始地址,而不是某一個(gè)值的起始地址。*a是一個(gè)值(二維元素)的起始地址。
        (gdb) p a[1]+1 $13 = (int *) 0xbffff32c 說明a[1]+1是一個(gè)值的地址,而不是一個(gè)數(shù)組的起始地址,因此a[i]+j是一個(gè)值(二維元素)的地址。
        (gdb) p *(a+1)+1 $6 = (int *) 0xbffff32c (gdb) p *(*(a+1)+1) $7 = 8736756,根據(jù)調(diào)試結(jié)果可知*(a+1)+1是一個(gè)值的地址。因此*(a+i)+j是一個(gè)值(二維元素)的地址。同時(shí)可知*(*(a+i)+j)是一個(gè)值(二維元素)。a[i][j]也是一個(gè)值。
        綜合上面的分析可知數(shù)組名A在作為右值時(shí)是數(shù)組首個(gè)元素(可能是一個(gè)值也可能是一個(gè)數(shù)組)的起始地址,而&A表示整個(gè)數(shù)組的起始地址。二維數(shù)組具體問題建議多去調(diào)試,根據(jù)調(diào)試分析其中的意義。多調(diào)試,多觀察,多理解。


        關(guān)鍵詞: C語言數(shù)組分

        評(píng)論


        技術(shù)專區(qū)

        關(guān)閉
        主站蜘蛛池模板: 怀远县| 二连浩特市| 云浮市| 乌拉特后旗| 浦江县| 泽库县| 巴东县| 元朗区| 桐乡市| 盐源县| 莲花县| 陆丰市| 曲麻莱县| 富顺县| 大姚县| 山西省| 太仓市| 卫辉市| 康乐县| 苗栗市| 海原县| 沙湾县| 贡嘎县| 万年县| 大庆市| 肥乡县| 改则县| 奉贤区| 新闻| 辰溪县| 武安市| 田林县| 紫云| 内乡县| 黄陵县| 黑龙江省| 阆中市| 嘉峪关市| 泰来县| 桐乡市| 万州区|