2011-05-09 68 views
8

我正在研究C中的最後一個明天,並且對於運算符sizeof有個問題。sizeof數組澄清

比方說,int的大小是32位,指針是64位。

如果有一個功能:

int 
foo (int zap[]) 
{ 
    int a = sizeof(zap); 
    return a; 
} 

因爲zap是一個指針,foo將返回8,因爲這是多少個字節如何需要存儲這個特殊的指針。然而,用下面的代碼:

int zip[] = { 0, 1, 2, 3, 4, 5 }; 
int i = sizeof(zip); 

i6 * sizeof(int) = 6 * 4 = 24

爲什麼是它的每個元素的元素的sizeof(zip)返回數倍大小,而sizeof(zap)返回a的大小指針?是不是zap的大小不明確,zip不是?編譯器知道zip6元素,但不知道可能有多大。

回答

8

這是C語法中的一種不對稱。在C中,不可能將一個數組傳遞給一個函數,所以當你在一個函數聲明中使用數組語句時,編譯器會將其作爲指針讀取。

在C中當您使用的陣列中的表達的陣列被隱式轉換爲指針到它的第一元件和例如爲當調用一個函數正是發生大多數情況下。在下面的代碼:

int bar[] = {1,2,3,4}; 
foo(bar); 

陣列被轉換爲指針的第一個元素,並且是函數接收什麼。

內隱轉換的這條規則並不總是能夠適用。當你發現例如sizeof操作符陣列上,甚至&運營商(-的地址)的作品原來的陣列(即sizeof(*&bar) == 4*sizeof(int))上。

在C A功能不能recevive數組作爲參數,它只能接收一個指針的第一個元素,或一個指針數組...或中,必須用一個結構陣列。

即使你把函數聲明括號之間的數...

void foo(int x[4]) 
{ 
    ... 
} 

這個數字完全是由編譯器忽略...那聲明編譯器是完全等同於

void foo(int *x) 
{ 
    ... 
} 

和例如甚至調用它傳遞一個數組具有不同的尺寸將不會觸發任何錯誤...

int tooshort[] = {1,2,3}; 
foo(tooshort); /* Legal, even if probably wrong */ 

(實際上是一個編譯器可能給予警告,但代碼是完全合法的C和必須的,如果編譯器遵循標準被接受)

如果你認爲有關數組這個規則時,函數參數是奇怪那麼我同意,但這是如何定義C語言的。

+0

數量並不被編譯器忽略,INT X [4]作爲函數參數意味着你必須通過的_exactly_ 4個元素的數組的指針。這與在代碼中其他地方寫入'int(* x)[4]'是一樣的。除此之外,這個答案指出了這個問題:參數的數組語法與程序中其他地方聲明的數組具有不同的含義。它是C語言的「特徵」之一。爲避免混淆,請始終使用「int * x」表示法來表示參數。 – Lundin 2011-05-09 06:56:59

+0

您可以指出它在標準中寫入括號內的數字必須等於傳遞數組的大小嗎?提示:考慮到你根本不能傳遞一個數組並且該函數實際上只接收一個指針,這將是一個奇怪的要求。當調用用'FOO的函數(巴)'其中'bar'是一個數組,數組已被轉換爲指針**即使對於編譯器**被認爲是函數調用之前。對轉換中已經放棄的尺寸信息施加限制是沒有意義的。 – 6502 2011-05-09 07:06:29

+0

@Lundin,對於數組參數的第一維,no基本上被忽略。此外,C99還有關鍵字'static'的可能性,以指定該函數對於項目至少*。但參數的類型仍然是'int *'。 – 2011-05-09 07:51:45

2

因爲zip是數組並且編譯器知道它的大小,所以編譯時的編譯時間爲。它只是使用兩個不同的東西,一些相同的符號在C.很平常的情況下

int 
foo (int zap[]) 

完全等同於

int 
foo (int *zap) 

編譯器不會有任何想法大ZAP怎麼可能是(所以它留給找到程序員的任務)。

+1

這個C常見問題是**無價**:http://c-faq.com/aryptr/index.html – cnicutar 2011-05-09 06:30:00

+0

即使您在括號內放置一個數字,但它仍然只是一個指針,而數字本身完全被編譯器忽略。所以它不是一個關於編譯器不知道大小的問題......它的C語言對函數參數列表中的數組有特殊的奇怪規則。 – 6502 2011-05-09 06:58:12

+0

@ 6502你是對的,很好的電話。在括號內加上一個數字會產生同樣的效果,這就是爲什麼它被強烈勸阻的原因。 – cnicutar 2011-05-09 07:00:44

-1

因爲它已經靜態初始化6個元素。

+0

有人想澄清downvote?我的回答和其他2人一樣,只是更簡潔一點而已? – 2011-05-09 06:28:16

+0

我沒有做downvote,但是如果「zip」被初始化或者沒有,那真的沒關係。這個問題全是關於C的奇怪的函數參數語法。 – Lundin 2011-05-09 07:02:07

0

zip的大小在編譯時已知,zap的大小不是。這就是爲什麼你得到sizeof(zap)上的指針大小和sizeof(zip)上的數組大小。

2

zip6 * sizeof(int)的內存塊,因此它的大小爲24(在您的體系結構上)。 zap(在函數聲明中它也可以寫爲int *zap),但是可以指向任何內存地址,編譯器無法知道從這個地址(甚至包含這個地址)開始分配了多少空間。

0

在某些情況下,指針會衰減。函數調用就是其中之一。