陣列 函式一些小細節

2021-07-22 18:18:53 字數 3433 閱讀 3823

陣列的空間是連續。

陣列大小是陣列的型別x陣列的個數。

固定大小陣列是在程式設計時就確定的 動態陣列是在執行時分配的。

組數是效率最高的資料結構,但需要空間連續,固不可以很大。

什麼時候陣列和指標可以相同呢?

所有作為

函式引數

的陣列名總是可以通過編譯器轉換為指標。在其他所有情況下(最有趣的情況就是「在乙個檔案中定義為陣列,在另乙個檔案中宣告為指標」),陣列的宣告就是陣列,指標的宣告就是指標,兩者不能混淆。但在是用陣列(在語句或表示式中引用)時,陣列總是可以寫成指標的形式,兩者可以互換。

對編譯器而言,乙個陣列就是乙個位址,乙個指標就是乙個位址的位址。

總結一下相同點的地方和不同點的地方:

宣告方面

:1、extern 如extern char a;不能寫成指標形式。 2

、定義,如char a[10];不能該寫成指標形式。 3

、函式的引數,如fun(char a)或fun(char *a)隨便寫,因為當陣列作為函式引數時,編譯都將把它轉化為指標形式處理。

在表示式中使用

:如c=a[i]也可以隨便寫,陣列形式或指標形式都可以。

標準c規定了三條規則:陣列與指標相同 1

、表示式中的陣列名(與宣告不同)白編譯器當作是乙個指向該陣列的第乙個元素的指標。 2

、下標總是與指標的偏移量相同。 3

、在函式引數的宣告中,陣列名被編譯器當作指向該陣列第乙個元素的指標。

在表示式中,指標和陣列是可以互換的,因為他們在編譯器裡的最終形式都是指標,並且都可以進行取下標運算。當然也有幾個極少見的例外:在下列情況下,對陣列的引用不能用指向該陣列第乙個元素的指標來代替:

(1)、陣列作為sizeof()的運算元顯然此時需要的是整個陣列的長度,而不是指向第乙個元素的指標。

(2)、使用&取陣列的位址,它所取的是整體陣列的乙個位址。

(3)、陣列是乙個字串常量初始值時。 c

語言把陣列小標該寫成指標偏移量的根本原因就是指標和偏移量是底層硬體所使用的基本模型。

標準規定作為「型別的陣列」的形慘的宣告應該調整為「型別的指標」。在函式形慘定義這個特殊情況下,編譯器必須把陣列形式改寫成指向陣列第乙個元素的指標形式,編譯器只向函式傳遞陣列的位址,而不是整個陣列的拷貝。

把作為形慘的陣列和指標等同起來是處於效率原因的考慮。

在c語言中,所有非陣列形式的資料實參均以傳值形式(對實參作乙份拷貝傳遞給呼叫的函式,函式不能修改作為實參的實際變數的值,而是只能修改傳遞給他的那份拷貝)呼叫。然而,如果要拷貝整個陣列,無論是在時間上還是空間上的開銷都是很大的,而且在大多數情況下你並不需要拷貝整個陣列,只要告訴函式那個位址就可以了。

我們看一下陣列形慘是如何被引用的:

fun(char p)

或fun(char *p)

c=p[i]

編譯器符號表顯示p可以取址,從堆疊指標sp偏移14個位置

執行時步驟1:從sp偏移14個位置找到函式的活動記錄,取出引數

執行時步驟2:取i的值,並於5081相加

執行時步驟3:取出位址(5081+i)的內容

注意:有一樣操作只能在指標裡進行而無法在陣列中進行,那就是修改它的值。陣列名是不可修改的左值,他的值是不能改變的。

先來看一下三個函式的宣告:

void

* malloc

(usigned size);

void

* realloc(

void

*ptr,

unsigned

newsize);

void

* calloc

(size_t numelements, size_t sizeofelement);

它們都包含在

#include

標頭檔案中,他們的返回值都是請求分配的位址,如果請求失敗就返回null

解釋一下這三個函式的用法、作用、區別。

malloc

()

malloc()

在記憶體的動態儲存區中分配一塊長度為size位元組的連續區域。引數size為需要的記憶體空間的長度,返回該區域的位址

calloc

()

calloc()與

malloc

相似,引數sizeofelement為申請位址的單位元素長度,numelements為引數個數

示例:由於malloc可以很方便的實現calloc的功能,所以我們一般不去使用calloc

realloc

()

realloc

()是給乙個已經分配了位址的指標重新分配空間,引數ptr為原有的空間位址,newsize是重新申請的位址空間

示例:

區別如下:

malloc

不能初始化所分配的記憶體空間,而函式calloc能。如果malloc函式分配的記憶體空間原來沒有被使用過,則其中的每一位可能都是0;反之,如果這部分記憶體曾經被分配過,則其中可能遺留各種各樣的資料,也就是說,使用malloc函式的程式開始時(記憶體還沒有被重新分配)能正常進行,但經過一段時間(記憶體已經被重新分配,可能會出現一些問題)。

calloc

會將所分配的空間中的每一位都初始化為零,也就是說如果你是字元型別或整數型別的元素分配記憶體,那麼這些元素將保證會被動的初始化為0,如果你為指標型別的元素分配記憶體,那麼這些元素通常會被初始化為空指標。如果你為實型元素分配記憶體,則這些元素會被初始化為浮點型的0。

realloc

可以對給定的指標所指向的空間進行擴大或縮小,無論是擴大還是縮小,原有的記憶體中的內容將保持不變,當然,對於縮小,則被縮小的那一部分的內容將會丟失,realloc並不保持調整後的記憶體空間和原來的 記憶體空間保持同一記憶體位址,realloc返回的指標很可能指向新的位址。

實現原理

malloc

、calloc函式的實質體現在,它有乙個將可用的記憶體連線為乙個長長的鍊錶(即所謂的空閒鍊錶)。呼叫malloc函式時,它沿連線表尋找乙個大到足以滿足使用者請求所需要的記憶體塊,然後將該記憶體塊一分為二(一塊的大小與使用者申請的大小一樣,另一塊就是剩下的位元組),接下來,將分配給使用者的那塊記憶體傳給使用者,並將剩下的那塊(如果有的話),返回到鍊錶上,呼叫free函式 時,它將使用者釋放的記憶體塊連線到空鏈上,到最後,空閒鍊錶會被切成很多的小記憶體片段,如果這時使用者申請乙個大的記憶體片段,那麼空閒鏈上可能沒有可能滿足使用者要求的片段了,於是malloc函式請求延時,並開始在空間中翻箱倒櫃的檢查記憶體片段,對它們進行整理,並將相鄰的小空閒塊合成較大的記憶體塊

realloc

是從堆空間上分配記憶體,當擴大一塊記憶體空間時,realloc試圖直接從現存的資料後面的哪些位元組中獲得附加的位元組,如果能夠滿足,自然天下太平,那麼如果後面的位元組不夠,問題就來了,那麼就使用堆上第乙個足夠滿足要求的自由空間塊,現存的資料然後就被拷貝到新的位置上,而老塊則放回堆空間,這句話傳遞的乙個很重要的資訊就是資料可能被移動。

一些小細節

1 c中printf計算引數時是從右到左壓棧的。定義乙個陣列 int arr 再定義乙個指標 sint prt arr printf d n ptr 此時ptr指向第乙個元素6 ptr 123展開為 ptr ptr 123 ptr 此時ptr指向第二個元素7 printf d,d n ptr,ptr...

Scanf函式的一些小細節

scanf函式式c語言的基本輸入函式,對於很對接觸過c語言的人都不會感到陌生,可是對於這個最基本的輸入函式,卻隱藏著一些容易讓人出錯的細節。1 函式原型 int scanf constchar format,2 format format 指向的控制串由以下三類 字元組成 格式控制符 空白字元 非空...

response一些小細節

1 response 向客戶機輸出資料。2 位元組流 outputstream 可以輸出任何的資料,而字元流 writer 只能寫字元資料 3 respone.setheader content type text html charset utf 8 控制瀏覽器,指定編碼是utf 8 上面語句等同...