2012-07-23 58 views
10

我想要得到一個數組的長度,比如int array[] = {1, 2, 3, 4}。我用sizeof來做到這一點。爲什麼sizeof(param_array)是指針的大小?

int length(int array[]) 
{ 
    return sizeof(array)/sizeof(int); 
} 

int main() 
{ 
    int array[] = {1, 2, 3, 4}; 
    printf("%d\n", length(array)); // print 1 
    printf("%d\n", sizeof(array)/sizeof(int)); // print 4 
} 

那麼,爲什麼在sizeof(array)功能length返回array指針大小?但在功能main,它的工作原理。

而且,我應該如何修改length函數來獲取數組的長度?

+1

是的,我知道這是一個C++的問題,但它包含了關於C作爲以及非常有用的信息:http://stackoverflow.com/questions/4810664/how-do-i-use-arrays-in -c – chris 2012-07-23 23:47:19

回答

18

一個特殊的C規則說,對於函數參數,數組類型是調整爲指針類型。這意味着:

int length(int array[]);

相當於

int length(int *array);

所以,當你計算sizeof你實際上是在計算指針的大小的數組。

(C99,6.7.5.3p7)類型的數組「的參數作爲的聲明‘’應被調整爲‘合格指針輸入’,其中類型限定符 (如果有的話)的那些內指定數組類型派生的[和]。「

+4

......這意味着你不能重寫'length()'來按你的意願工作 - 如果一個函數需要知道數組的大小,它需要作爲一個單獨的參數傳遞給該函數。 – caf 2012-07-24 00:16:45

+0

@caf我同意你的意見。有關更多信息,這樣做很有意義,特別是在具有r0,r1,r2,r3 32位寄存器的ARM處理器上時。因此可以在r0中傳遞一個指針,而不必使用堆棧。 – 2016-10-17 23:29:48

2

C不存儲關於包含變量的數組大小的運行時元數據。你將不得不把它存儲在某個地方。

int []類型的在方法中長度上下文中的變量只是一個指向的內存塊。這就是爲什麼尺寸與系統上任何其他指針的尺寸相同的原因。

的sizeof訪問在編譯時數組(如你主要功能),這反而返回由數組佔用的字節數。

+1

「類型爲int []的變量只是指向內存塊的指針」 - 在一般情況下不正確。一個'int []'*類型的變量是*一塊內存。它不是一個指針。 'int []'代表指針的唯一上下文是函數參數聲明,它是一個*特殊情況*。 – AnT 2012-07-23 23:54:11

+0

澄清它是在方法length()*的上下文中的指針*。感謝您指出了這一點。 – 2012-07-24 00:50:19

3

在主程序中,編譯器知道數組的長度。在子程序中,它沒有。特別是在子程序中,類型int[]的參數與int *類型的參數相同。另一方面,在主程序中,array的類型爲int[4]。 (你可以通過嘗試在main這一邊指定另一個值array進行測試,編譯器會報錯)。

0

因爲變量數組裏面的長度和外面的長度不一樣。您必須在main函數中保留sizeof(array)/ sizeof(int)。

4

將數組傳遞給函數時,數組會衰減爲指針。

0

要修改代碼,以便length可以得到數組的長度,把它變成一個宏:

#define length(x) (sizeof(x)/sizeof(*x)) 

對於您的代碼示例,這將表現爲你期望的那樣。

請注意,這將只有工作在靜態分配的數組,並且只有在使用原始數組調用時(使用指向數組的指針時不起作用)。這是因爲當你編寫sizeof(x),其中x是一個指向數組的指針時,編譯器將從字面上解釋它。它沒有任何方法將x映射回它在評估sizeof之前指向的數組。

1

如果你想length要知道在數組中傳遞的真實大小的,這些信息將被傳遞中,爲大家說。但它有可能爲它與信息還內置接收到數組的引用:

int length(int n, int (* array)[n]) 
{ 
    return sizeof(*array)/sizeof(int); 
} 

int main() 
{ 
    int array[] = {1, 2, 3, 4}; 
    printf("%d\n", length(4, &array)); // print 1 
    printf("%d\n", sizeof(array)/sizeof(int)); // print 4 
} 

我不知道有什麼好,其實做了你,不過,由於大小在已經提供第一名。但是您會發現sizeof運營商在這種情況下按照您的要求工作。

4

正如其他answerers已經指出,一個函數聲明採取一個數組編譯相同,就像它採取了一個指針。

我看過做長度方法的最常用方法是使用#define,但如果使用模板玩技巧,則可以使您的功能正常工作。

template <size_t _Size> inline int length(int(& array)[_Size]) 
{ 
    //return sizeof(array)/sizeof(int); 
    return _Size; 
}; 

int array[] = {1, 2, 3, 4}; 
printf("%d\n", length(array)); // print 4 

有了您的長度爲4的數組,這個被編譯成需要長度爲4陣列的方法,並返回一個靜態4.這也有個好處,如果你試圖通過一些不一個數組,編譯器會給出一個錯誤,而#define方法不會。

int* foo = array; 
printf("%d\n", length(foo)); 
    // error C2784: 'int length(int (&)[_Size])' : could not deduce template 
    //  argument for 'int (&)[_Size]' from 'int *' 
    // test.cpp(56) : see declaration of 'length' 
+1

問題標記爲C,而不是C++。 – jxh 2012-07-24 02:02:40

+0

啊,很對。哦,也許他會發現它很有用。 – 2012-07-24 05:02:40

相關問題