日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

数组和指针联系

發(fā)布時(shí)間:2025/3/15 编程问答 34 豆豆
生活随笔 收集整理的這篇文章主要介紹了 数组和指针联系 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

?

轉(zhuǎn)載:http://www.cnblogs.com/yanlingyin/

數(shù)組和指針經(jīng)常出現(xiàn)于編程語言中、也許上課的時(shí)候老師也說過數(shù)組和指針有區(qū)別、參考書上也應(yīng)該講過,你是不是也不曾透徹的理清過?

這篇博文主要從內(nèi)存和編譯的角度指出了數(shù)組和指針在訪問方式上的區(qū)別、至于他們在函數(shù)調(diào)用的區(qū)別、以及它們的聯(lián)系將在下一篇中詳細(xì)討論。

?

為了說的清楚些、會(huì)先說一些基礎(chǔ)的部分、如果你已經(jīng)掌握大可跳過

What's a Declaration? What's a Definition??聲明和定義

c語言的對象必須有且只有一個(gè)定義,但可以有多個(gè)聲明(extern)這里說的對象和面向?qū)ο笾械膶ο鬀]有關(guān)系。

A definition is the special kind of declaration that creates an object; a declaration indicates a name?
that allows you to refer to an object created here or elsewhere。

定義是一種特殊的聲明、它創(chuàng)建了一個(gè)對象;聲明簡單的說明了在其他地方創(chuàng)建的對象的名字,它允許你使用這個(gè)名字。

可以簡單的這樣理解:

聲明Declaration:描述在其他地方創(chuàng)建的對象,并不分配內(nèi)存。(可以出現(xiàn)在多個(gè)地方)

定義Definition:產(chǎn)生一個(gè)新的對象,并分配內(nèi)存。(只能出現(xiàn)一次)

?

How Arrays and Pointers Are Accessed -數(shù)組和指針是如何訪問的

數(shù)組和指針在內(nèi)存中的訪問方式是不一樣的。這里先要注意一下“地址y”和“地址y的內(nèi)容”的區(qū)別。“地址y”表示變量y在內(nèi)存中的地址,而“地址y的內(nèi)容”指的是

位于這個(gè)地址中的內(nèi)容,也就是變量y的值。大多數(shù)編程語言中用同一個(gè)符號來表示這兩個(gè)東西,而由編譯器根據(jù)上下文環(huán)境判斷它的含義。

以一個(gè)簡答的賦值為例:

上文中的x指的是x所代表的地址,而y的含義是y的內(nèi)容。

出現(xiàn)在賦值符號左邊的值稱為左值、賦值符號右邊的稱為右值。編譯器為每個(gè)變量分配地址(左值)。這個(gè)地址在編譯時(shí)可知且一直存在,而它的右值在運(yùn)行時(shí)

才能知道。通俗的說:每個(gè)變量都有一個(gè)地址,這個(gè)地址在編譯時(shí)可以知道,而地址里存儲(chǔ)的內(nèi)容(也就是變量的值)只有在運(yùn)行時(shí)才能知道。如果需要用到變量

的值,(也就是已知地址存儲(chǔ)的值)那么編譯器發(fā)出指令從指定地址讀入變量值并放入相應(yīng)寄存器中。

  這里的關(guān)鍵是地址在編譯時(shí)可知、如果要對進(jìn)行一些操作(比如說加上偏移量之類的)可以直接操作。相反、對于指針,必須在運(yùn)行時(shí)取得它的地址,然后才能

對它進(jìn)行接觸引用操作。下圖展示了對數(shù)組下標(biāo)的引用:

  這樣我們就可以解釋為什么extern char a[]和extern char a[100]相同的原因了。這兩個(gè)什么都是表名a是一個(gè)數(shù)組,也就是一個(gè)內(nèi)存地址,

數(shù)組內(nèi)的字符可以由這個(gè)地址找到。

和上面不同的是,如果聲明的是一個(gè)指針,如 ?extern char *p,它表示p指向一個(gè)字符,為了取得這個(gè)字符,必須知道地址p的內(nèi)容,把它作為字符的地址

并從這個(gè)地址中取得這個(gè)字符。

如果是數(shù)組a[],那么可以直接用數(shù)組名來訪問數(shù)組中的元素,因?yàn)樗膬?nèi)容就是第一個(gè)元素, 他的下一個(gè)地址也就對應(yīng)了下一個(gè)數(shù)組元素的地址。

如果是指針*a,先要取出地址a的內(nèi)容,再把它作為變量的地址并從這個(gè)地址中取得變量的內(nèi)容。

?

數(shù)組和指針的其他區(qū)別:

?

定義指針時(shí),編譯器并不為它所指向的對象分配空間,只為指針本身分配空間。除非在定義同時(shí)付給一個(gè)指針一字符竄常量進(jìn)行初始化。

如:char *p = "breadfruit";?

一般情況下初始化指針時(shí)創(chuàng)建的字符串變量被定義為只讀。如果試圖修改就會(huì)出現(xiàn)未定義的行為。

?

這篇文章主要是從訪問形式上對數(shù)組和指針的區(qū)別做了些小的總結(jié),而對于數(shù)組和指針在函數(shù)調(diào)用中、已經(jīng)更本質(zhì)的區(qū)別、什么時(shí)候數(shù)組

和指針又是等同的、將在下一篇博文中給出。如果完全弄清楚了、對今后的編程也會(huì)有不小的幫助。

?

什么時(shí)候數(shù)組和指針相同(When an Array Is a Pointer )

在實(shí)際應(yīng)用中,他們可以互換的情形要大大多于不能互換的情形。首先再回顧一下聲明和定義,(上一篇中有提到這里在深入一下)

聲明本身還可以進(jìn)一步分為三種情況:

1)外部數(shù)組的聲明(external array)

2)數(shù)組的定義(它是聲明的一種特殊情況,它分配內(nèi)存空間,并可能提供一個(gè)初值)

3)函數(shù)參數(shù)的聲明

所有作為函數(shù)參數(shù)的聲明在編譯時(shí)總是會(huì)轉(zhuǎn)換為指針(指向數(shù)組第一個(gè)元素),而其他情況的聲明,數(shù)組就是數(shù)組 ,指針就是指針

可以用如下的圖來說明他們的關(guān)系:

?

稍微總結(jié)一下:

對于編譯過程中數(shù)組會(huì)轉(zhuǎn)化為指針的情況,數(shù)組和指針可以互換,比如:聲明為函數(shù)參數(shù)的時(shí)候 fun(int a [])和fun(int *a )是等同的。因?yàn)榫幾g的過程中fun(int a [])

中的數(shù)組會(huì)轉(zhuǎn)化為指針形式,也就和fun(int *a )的效果一樣了。

如果編譯到時(shí)候數(shù)組不被當(dāng)做指針處理,那么聲明的時(shí)候不能等同。對于這種情況,數(shù)組和指針是不一樣的的,在運(yùn)行時(shí)的表示形式也不一樣,并可能產(chǎn)生不同的代碼。

對編譯器而言,一個(gè)數(shù)組就是一個(gè)地址,一個(gè)指針就是地址的地址。

c語言標(biāo)準(zhǔn)對此做了如下說明:

1)An array name in an expression (in contrast with a declaration) is treated by the compiler as a pointer to the first element of the array?
(paraphrase, ANSI C Standard, paragraph 6.2.2.1).

2)A subscript is always equivalent to an offset from a pointer (paraphrase,?

ANSI C Standard, paragraph 6.3.2.1).

3)An array name in the declaration of a function parameter is treated by?

the compiler as a pointer to the first element of the array (paraphrase, ANSI?
C Standard, paragraph 6.7.1).

即:

1)表達(dá)式中的數(shù)組名(與聲明不同)被編譯器當(dāng)做一個(gè)指向該數(shù)組第一個(gè)元素的指針

2)下標(biāo)總是與偏移量相同

3)在函數(shù)參數(shù)的聲明中,數(shù)組名被編譯器當(dāng)做指向該數(shù)組第一個(gè)元素的指針

我覺得有必要對上文中出現(xiàn)的“表達(dá)式”做一個(gè)解釋

int arry[10]={,,,,,};

int a=arry[2];

那么第二句中的int a=arry[2];就是所謂的表達(dá)式中出現(xiàn)的數(shù)組名了,這個(gè)時(shí)候編譯器會(huì)把數(shù)組名arry當(dāng)做指向數(shù)組第一個(gè)元素的指針,也就是arry[0]的地址

下標(biāo)總是與偏移量相同,也就是arry[2]中的下標(biāo)2和arry[2]這個(gè)元素在內(nèi)存中相對于第一個(gè)元素的偏移量也是2它們是相同的。這樣就能解釋用數(shù)組下標(biāo)可以取得

相應(yīng)的數(shù)組中的某個(gè)元素了。(當(dāng)然,在內(nèi)存中還要考慮步長因素)

有了上面的分析,下面的容易弄懂了

如果聲明: int a[10] ,*p , i=2

那么我們可以通過下面的任一種方式來訪問a[i](每一列為一組,共三種)

p=a;   p=a;   p=a+i;?
p[i];   *(p+i);   *p;

在表達(dá)式中,數(shù)組和指針是可以互換的, 因?yàn)樗鼈冊诰幾g器里都是指針形式,并且都能進(jìn)行去下標(biāo)操作。

數(shù)組和指針的遍歷

為了更好的理解,下面通過一個(gè)例子說明數(shù)組和指針的聯(lián)系和區(qū)別。(有點(diǎn)難理解~哦)

將在內(nèi)存訪問的角度來討論數(shù)組和指針遍歷

數(shù)組遍歷:

for(i=0;i<10;i++)

a[i]=0

遍歷過程:

1)把a(bǔ)的左值放入寄存器R1(也就是把a(bǔ)的物理地址也即數(shù)組的首地址存入R1)  可提到循環(huán)外

2)把i 的左值放入R2,同上,就是吧i 的物理地址放入R2  可移到循環(huán)外

3)把 [R2] ?的右值放入 R3 也就是把變量i ?的大小放入R3,(這里有點(diǎn)匯編的味道)

4)如果需要,調(diào)整R3 的步長,把R1 +R3 的值放入R4  解釋:R1為數(shù)組的首地址,R3為偏移量,所以R4 就是當(dāng)前操作數(shù)的地址

5)把0放入 [R4]

注:上面的R1-R4 看看做是寄存器,符號 [n] 表示的是:內(nèi)存地址為n的值

”可以移到循環(huán)外“說明它在整個(gè)過程中不會(huì)改變,比如數(shù)組的首地址,變量 i 地址

左值和右值的概念在上面鏈接給出的博文中有闡述

指針遍歷:

p=a

for(i =0 ;i < 10 ; i ++)

  *p++=0

遍歷過程:

1)p 所指對象的大小放入R5  可移到循環(huán)外

2)左值 p 放入R1    可移到循環(huán)外

3)[R0]放入R1

4)0存到[ R1]

5) R5+R1的結(jié)果存入R1

6)R1 存到[R0]

其實(shí),這兩兩種訪問方式也可看做是對上一篇博客中的訪問方式的一個(gè)更深的理解。

要操作一個(gè)變量就要得到這個(gè)變量的地址,取得地址的方式數(shù)組和指針的區(qū)別和聯(lián)系。這里就不在啰嗦,有興趣的朋友可以參見上一篇博文

http://www.cnblogs.com/yanlingyin/archive/2011/11/29/2268391.html

?為什么C把數(shù)組形參當(dāng)做指針

把作為形參的數(shù)組當(dāng)做指針來考慮其實(shí)是出于效率考慮。C中,所有非數(shù)組形式的數(shù)據(jù)實(shí)參均為值傳遞形式,值傳遞也就是調(diào)用函數(shù)的時(shí)候,把實(shí)參

拷貝一份給調(diào)用函數(shù),就是說函數(shù)操作的是實(shí)參的拷貝而不是實(shí)參本身。(所以值傳遞的時(shí)候如果在函數(shù)中改變參數(shù)值,等調(diào)用結(jié)束后對實(shí)際的實(shí)參沒有

影響,因?yàn)橹祩鬟f中函數(shù)操作的只是實(shí)參的一份拷貝而并不是實(shí)參本身)

而對于數(shù)組,如果每次執(zhí)行函數(shù)都要拷貝整個(gè)數(shù)組的話,就會(huì)花費(fèi)大量的時(shí)間和空間開銷,所有對于數(shù)組,C開用的機(jī)制是告訴函數(shù)數(shù)組的首地址,直接對

數(shù)組進(jìn)程操作。

了解C++的朋友對于這應(yīng)該就能更好地理解了,C++中參數(shù)傳遞分為值傳遞和引用傳遞,有興趣的可以自行查閱資料、這不是本文終點(diǎn)不在復(fù)數(shù)

數(shù)組和指針的可交換性總結(jié):Arrays and Pointers Interchangeability Summary?

1. An array access a[i] is always "rewritten" or interpreted by the compiler as a pointer access *(a+i);?
2. Pointers are always just pointers; they are never rewritten to arrays. You can apply a?
subscript to a pointer; you typically do this when the pointer is a function argument,?
and you know that you will be passing an array in.?
3. An array declaration in the specific context (only) of a function parameter can equally?
be written as a pointer. An array that is a function argument (i.e., in a call to the?
function) is always changed, by the compiler, to a pointer to the start of the array.?
4. Therefore, you have the choice for defining a function parameter which is an array,?
either as an array or as a pointer. Whichever way you define it, you actually get a?
pointer inside the function.?
5. In all other cases, definitions should match declarations. If you defined it as an array,?
your extern declaration should be an array. And likewise for a pointer.

1)對于a [i]這種形式的訪問數(shù)組,通常被解釋為指針形式*(a + i) ? 也就是上文中所說的“表達(dá)式”的情形

2)指針就是指針,沒有說指針轉(zhuǎn)化為數(shù)組的情況,你可以用下標(biāo)的形式去訪問指針,但一般都是指針作為函數(shù)參數(shù)時(shí),而且傳入的是一個(gè)數(shù)組

3)在函數(shù)參數(shù)的聲明中,數(shù)組可以看做指針,(也只有這種情況)

4)當(dāng)把一個(gè)數(shù)組定義為函數(shù)參數(shù)時(shí),可以定義為數(shù)組,也可以是指針

5)其他的所有情況,聲明和定義必須匹配。如果定義了一個(gè)數(shù)組,在其他文件中對它也必須聲明為數(shù)組。指針也一樣。

總結(jié)

以上是生活随笔為你收集整理的数组和指针联系的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。