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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

浅谈数组和指针

發(fā)布時間:2024/1/18 编程问答 21 豆豆
生活随笔 收集整理的這篇文章主要介紹了 浅谈数组和指针 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

???? 這應該不是議數(shù)據(jù)和指針,應該是閱讀筆記吧!但是其這個題目更好點。

????? C專家編程第四章內容:令人震驚的事實:數(shù)組和指針并不相同。自己也收獲不小,了解很多基礎的東西,對那些初入C開發(fā)人員有很好的幫助。那廢話少說吧。

???? 我們總以為數(shù)據(jù)和指針是完全等同的,兩者是可以互換的,這種說法是片面的。我們在編程中經(jīng)常使用全局變量,在其他文件中聲明中也可以使用這個全局變量。下面就舉個例子說明:

文件1

Int mango[100];

文件2

Extern int *mango;? /**/

...

/*一些使用mango的代碼*/

????? 這里,文件1定義int 變量mango,但文件2聲明它為指針int *型,這里顯然是類型不匹配,也說明了數(shù)組和指針并不是完全等同的。這樣使用肯定是錯誤的,代碼不可能正常運行。那么應該怎么聲明呢, 如下:

Extern int mango【】;/**/

說明: 語句聲明mango是個int*型;聲明mango為int 型數(shù)組,長度尚未確定,其存儲在別處定義。

?????

?? 1 ?那么什么是聲明?什么是定義?

??????? 在C語言中對象必須有且只有一個定義,但可以有多個聲明。定義是一個特殊的聲明,它創(chuàng)建一個對象;聲明只是說明了在其他地方創(chuàng)建了這個對象,它允許在這里使用:

*******************************************************************************

定義???? 只能出現(xiàn)在一個地方? 確定對象的類型并分配內存,用于創(chuàng)建新的對象

聲明???? 可以多次出現(xiàn)??????? 描述對象的類型,用于指代其他地方定義的對象

*******************************************************************************

??? 只要記住下面的內容可以分清定義和聲明:

聲明相當于普通的聲明:它說明的并非自身,而是描述其他的地方創(chuàng)建的對象。

定義相當于特殊的聲明:它為對象分配內存。

?????? Extern 對象聲明告訴編譯器對象的類型和名字,對象的內存分配在別處進行。由于并未在聲明中為數(shù)組分配內存,所以并不需要提供關于數(shù)組長度的信息。對于多維數(shù)組需要提供除最左邊一維其他維的長度—這是給編譯器足夠的信息產生相應的代碼。

?? 2 、數(shù)組和指針式如何訪問的

???? 這里講述對數(shù)組的引用和對指針的引用有何不同之處,首先需要注意的是“地址y“和“地址y的內容”之間的區(qū)別。這里一個相當微妙之處,是在大多數(shù)編程語音中我們用同一個符號來表示這兩個東西,有編譯器根據(jù)上下文環(huán)境來判斷他的具體含義。以一個簡潔的例子來說明:

???

????? 出現(xiàn)在賦值符左邊的符號有事被稱為左值(由于它位于“左手邊”或“表示地點”),出現(xiàn)在賦值符右邊的符號有時則被稱為右值(由于它位于右手邊)。編譯器為每個變量分配一個地址(左值),這個地址在編譯時可知,而且該變量在運行時一直保存于這個地址。相反,存儲于變量中的值(右值)只有在運行時才知。如果需要用到變量中存儲的數(shù)值,編譯器就發(fā)出質量從指定地址讀取變量并將它存儲在寄存器中。

????? 這也是為什么在if(-1 == x)判斷語句中,如果將“==”誤寫為“=”編譯器會報警的原因(相信很多人只知道這么用,不知道為什么吧?)

??? 這里的關鍵在于每個符號在編譯時可知。所以如果編譯器需要一個地址(可能還需要加上偏移量)來執(zhí)行某種操作。它可以直接進行操作,并不需要增加指令首先取得具體的地址,相反對于指針在運行時首先取得它的當前值,然后才能對它進行接觸引用操作。具體看下圖:

?????? 這也是為什么extern char a[] 與 extern char a[100]等價的原因。這兩個都說明a是個數(shù)組,也就是個內存地址,數(shù)組內的字符可以從這個地址中找到。編譯器并不需要知道這個地址有多長,因為它只產生偏離起始地址的偏移地址。從數(shù)據(jù)中提取一個數(shù)值,只需要簡單的知道現(xiàn)實a的地址加上下標,需要的字符就位于這個地址中。

???? 相反,如果聲明extern char *p,它告訴編譯器P是個指針,它指向的是一個字符。為了取得這個字符,必須知道P的內容,把他作為字符的地址取其內容就是這個字符,指針的訪問比較靈活,但需要增加一次額外的提取。

??? 定義成指針,但以數(shù)組方式引用

現(xiàn)在讓我看下定義成指針,當以數(shù)組方式引用會發(fā)生什么,看下面的例子:

?

對照圖C的訪問方式

Char *p = abcdefgh;?? ...?? p[3]

和圖A的訪問方式:

Char a[] = abcdefgh”;? ....? a[3]

在這兩種情況下,都可以取得字符‘d’,但是兩者的途徑是不一樣的。

? 當書寫了 extern char *p,然后用p3】來引用其中的元素時,其實質是圖A和圖B的訪問方式的組合。首先,進行圖B所示的間接引用。然后,如圖A所示用下標作為偏移量進行直接訪問。更為正式的說明是,編譯器將會:

1.?????? 取得符號P的地址,提取存儲于此處的指針。

2.?????? 把下標所表示的偏移量與指針的值相加,產生一個地址。

3.?????? 訪問上面的地址,取得數(shù)值。

?到這也許已經(jīng)知道為什么文章開頭舉得例子中文件2中聲明Extern int *mango;? /**/

為什么會出現(xiàn)編譯失敗的問題?既然把P聲明成指針,那么不管P原先定義為指針還是數(shù)組,都會按照上面所示的三個步驟進行操作,但是只有當P原來定義成指針時,上面這個方法才是正確的。考慮上面那個問題。當用mangoi】這種形式提取這個聲明的內容時,實際上得到是一個字符,按照上面的方法,編譯器卻把它當成一個指針,把ACSII字符當作成地址顯然是錯誤的。

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

NO

指針

數(shù)組

1

保存數(shù)據(jù)的地址

保存數(shù)據(jù)

2

簡潔訪問數(shù)據(jù)。首先取得指針的內容,把它當成地址,然后從這個地址取提取數(shù)據(jù)。如果指針有一個下標【i】,那么就把指針的內用加上i的地址,從中提取數(shù)據(jù)

直接訪問數(shù)據(jù)。Ai】只是簡單地以a+i為地址取得數(shù)組。

3

通常用于動態(tài)內存分配

通常用于固定數(shù)目其數(shù)據(jù)類型相同的元素

4

相關函數(shù)malloc()和free()

隱身分配和刪除

5

通常指匿名數(shù)據(jù)

自身即為數(shù)據(jù)名

?

再議數(shù)組:

??

1、 什么時候數(shù)組和指針相同

在實際的運用過程中,數(shù)組和指針互換的情景比兩者不可互換的情形更為常見,讓我們分別來考慮“聲明”和“使用”兩種情況。

?

聲明本來還可以分為3中情況:

????????? 外部數(shù)組的聲明;

????????? 數(shù)組的定義(記住,定義是聲明的一種特殊情況,它分配內存空間,并提供一個初始值);

????????? 函數(shù)參數(shù)的聲明。

所有作為函數(shù)參數(shù)的數(shù)組名總是可以通過編譯器轉換為指針。在其他情況下,數(shù)組的聲明就是數(shù)組,指針的聲明就是指針,兩者不能混淆。但是在使用數(shù)組時,數(shù)組總是可以寫成指針的形式,兩者可以互換。下面是總結:

?

為什么會發(fā)生混淆

?

當人們學習編程時,一開始總是把所有的代碼都放在一個函數(shù)里。隨著水平的進步,他們把代碼分別放在幾個函數(shù)中,在水平繼續(xù)提高后,他們最終學會了如何用幾個文件來構造個程序。在這個過程中,他們可以看到大量的作為函數(shù)參數(shù)的數(shù)組和指針,在這種情況下,他們是完全可以互換的,如下所示:

char my_array[10]; char *my_ptr; ... i = strlen(my_array); j = strlen(my_ptr);printf("%s,%s",my_array,my_ptr);

上面清晰地展示了數(shù)組和指針的課互換性,人們很容易忽視這只是放生在一種特定的上下文環(huán)境中,也就是說作為一個函數(shù)調用的參數(shù)使用。更糟的是它可以如下編寫:

printf("array at location %x holds string %s",a,a);

??在同一個語句中,即把數(shù)組名作為一個地址(指針),有把他作為一個字符數(shù)組。

?

? 在C標準中對“什么時候數(shù)組和指針時相同的”作了如下的聲明:

規(guī)則1:表達式中的數(shù)組名(與聲明不同)被編譯器當做一個指向該數(shù)組第一個元素的指針。

規(guī)則2:下標總是與指針的偏移量相同。

規(guī)則3:在函數(shù)參數(shù)聲明中,數(shù)組名悲編譯器當做指向該數(shù)組第一個元素的指針

下面詳細介紹這3個規(guī)則的含義:

規(guī)則1:“表達式數(shù)組名”就是指針

?? 上面的規(guī)則1,2一起理解,就是對數(shù)組下標的引用總是可以寫成“一個指向數(shù)組的起始地址的指針加上偏移量”。例如,假如我們聲明:

int a[10],*p,i = 2; /*我們可以通過下面集中方法訪問a[i]*/ p = a; p[i]; /*****************/ p = a; *(p + i); /******************/ p = a + i; *p;
? 應該還有很多方法。對數(shù)組的引用如a[i]在編譯時總是被編譯器改寫成*(a+i)的形式,C語言要求編譯器必須具備這個概念性的行為。取指針或者數(shù)組名+方括號【】中的下標 就是訪問元素的地址,再取其值。所以,你也記住,在表達式中,指針和數(shù)組時可以互換的,因為他們在編譯器的最終都是以指針的形式。因此我們也可以理解下面的取值的表示方法為什么相同了并都是正確的。

a[6] = ......; 6[a] = .....;

規(guī)則2:C語言把數(shù)組下標作為指針的偏移量

?? 我們通常認為:在編寫數(shù)組算法時,使用指針比數(shù)組 更效率 。這種說法在通常情況下是錯誤的。在一維數(shù)組和指針引用所產生的代碼并不具有顯著的差別。這里可以參考前面的內容,自己在研究下。

規(guī)則3:作為函數(shù)參數(shù)的數(shù)組名等同于指針

?
術語定義例子
形參(parameter)他是一個變量,在函數(shù)定義或聲明的原型
中定義。又稱形式參數(shù)
int power(int base;int n);
base,n都是形參
實參(argument)在函數(shù)實際調用過程中傳遞給函數(shù)的值。I = power(10,2);
10和2是實參,

在標準中規(guī)定,類型的數(shù)組 的形參的聲明應該調整為 類型的指針。下面三種寫法都是一樣的

my_function (int *a); my_function (int a[]); my_function (int a[200]);

??????數(shù)組形參是如何被引用的?

??? 下圖展示了對一個下標形式的數(shù)組形參進行訪問所需要的幾個步驟:

? 注意:有一種操作只能在指針里進行而無法在數(shù)組中進行,那就是修改它的值。數(shù)組名是不可修改的左值,它的值是不能改變的。

?***********************************************************************************************************************************************************************

錯誤1 :定義數(shù)組,聲明指針

? ? 文件 1 中定義如下:
chara[100];
文件 2 中聲明如下:
externchar*a;
? ? ?這里,文件 1 中定義了數(shù)組 a,文件 2 中聲明它為指針。這有什么問題嗎?平時不是總說數(shù)組與指針相似,甚至可以通用嗎?但是,很不幸,這是錯誤的。通過上面的分析我們也能明白一些,但是“革命尚未成功,同志仍需努力” 。你或許還記得我上面說過的話:數(shù)組就是數(shù)組,指針就是指針,它們是完全不同的兩碼事!他們之間沒有任何關系,只是經(jīng)常穿著相似的衣服來迷惑你罷了
下面就來分析分析這個問題:?


?

?

?










?extern char * a;


錯誤2:定義指針,聲明數(shù)組:

? ??顯然, 按照上面的分析, 我們把文件 1 中定義的數(shù)組在文件 2 中聲明為指針會發(fā)生錯誤。同樣的,如果在文件 1 中定義為指針,而在文件中聲明為數(shù)組也會發(fā)生錯誤:
文件 1
? ? ? char*p = “abcdefg”;
文件 2
? ? ? extern charp[];
? ? ? 在文件 1 中, 編譯器分配 4 個 byte 空間, 并命名為 p。 同時 p 里保存了字符串常量 “abcdefg”的首字符的首地址。這個字符串常量本身保存在內存的靜態(tài)區(qū),其內容不可更改。在文件 2中,編譯器認為 p 是一個數(shù)組,其大小為 4 個 byte,數(shù)組內保存的是 char 類型的數(shù)據(jù)。在文件 2 中使用 p 的過程如下圖:





總結

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

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