2010-03-08 57 views
10

我該如何可靠地獲取C風格數組的大小?經常推薦的方法似乎是使用sizeof,但它並不在foo功能,其中x在傳遞工作:如何可靠地獲取C風格數組的大小?

#include <iostream> 

void foo(int x[]) { 
    std::cerr << (sizeof(x)/sizeof(int)); // 2 
} 

int main(){ 
    int x[] = {1,2,3,4,5}; 
    std::cerr << (sizeof(x)/sizeof(int)); // 5        
    foo(x); 
    return 0; 
} 

答案this question建議sizeof但他們不說,它(顯然?)如果您傳遞數組,則不起作用。那麼,我必須使用哨兵嗎? (我不認爲我的foo功能的用戶總是可以信任的把一個哨兵在最後。當然,我可以使用std::vector,但我沒有得到漂亮的語法速記{1,2,3,4,5}

+1

http://stackoverflow.com/questions/1810083/c-pointers-pointing-to-an-array-of-fixed-size – AnT 2010-03-08 20:44:56

+0

如果你的函數的用戶不做文檔告訴他們做的事情,那是他們的問題不是你的問題。不可能防止無知的API濫用。 – 2010-03-08 20:52:15

+0

'foo'中的'x'是一個指針,而不是一個數組。見http://stackoverflow.com/questions/232691/how-can-i-get-the-size-of-an-array-from-a-pointer-in-c,http://stackoverflow.com/questions/1975128 /的sizeof-AN-陣列內式C-編程語言。另外,dup:http://stackoverflow.com/questions/37538/c-how-do-i-determine-the-size-of-my-array – outis 2010-03-08 20:53:51

回答

15

在C中,C中的參數實際上只是指針,因此sizeof()將不起作用。您或者需要將尺寸作爲另一個參數傳遞,或者使用標記 - 以最適合您的設計爲準。

其他一些選項:

其他一些信息:

  • 對於C++而不是將原料數組指針,你可能希望有參數使用的東西,包裝陣列中的類跟蹤數組大小並提供以安全方式將數據複製到數組中的方法的模板。像STLSoft's array_proxy templateBoost's boost::array可能會有所幫助。我以前使用過array_proxy模板,效果不錯。在使用參數的函數內部,您可以得到類似於操作的std::vector,但函數的調用者可以使用簡單的C數組。沒有數組的拷貝 - array_proxy模板幾乎自動處理數組指針和數組的大小。

  • 宏在C用於確定元素的數量在數組(當的sizeof()可能會幫助 - 也就是說,你不處理一個簡單的指針。):Is there a standard function in C that would return the length of an array?

3

您可以傳遞大小,使用標記或更好地使用std :: vector。雖然標準::載體缺乏初始化列表仍然很容易構建一個向量與一組元素(雖然不是很漂亮)

static const int arr[] = {1,2,3,4,5}; 
vector<int> vec (arr, arr + sizeof(arr)/sizeof(arr[0])); 

性病:: vector類也使得犯錯誤困難得多,這在黃金中是值得的。另一個好處是所有C++都應該熟悉它,大多數C++應用程序應該使用std :: vector而不是原始C數組。

作爲一個快速的注意,C++ 0x中增加了Initializer lists

std::vector<int> v = {1, 2, 3, 4}; 

您還可以使用Boost.Assign做同樣的事情,雖然語法是更令人費解的一點。

std::vector<int> v = boost::assign::list_of(1)(2)(3)(4); 

std::vector<int> v; 
v += 1, 2, 3, 4; 
2

C提供此沒有本地支持。一旦數組超出其聲明的範圍,其大小就會丟失。

可以傳遞數組的大小。如果你總是保持規模,你甚至可以將它們捆綁到一個結構中,儘管這樣你會有一些書本費用。

1

這個怎麼樣?..

template <int N> 
void foo(int (&x)[N]) { 
    std::cerr << N; 
}
+0

-1:這是一個可怕的想法。 – Brian 2010-03-08 21:14:39

+1

@Brian:根據具體情況,這可能也可能不是一個壞主意。你爲什麼覺得這很可怕? 這是一個好主意,因爲如果你傳遞一個指針,它就不會編譯。 如果函數很大並且調用了許多不同的數組大小,它會很糟糕 - 它會生成一堆函數。另一種方法可能是讓這個foo轉向並調用private/internal foo_internal(int * x,size_t length); 這取決於使用。我發現這個技術對於字符串函數很有用,如果使用不當,它往往會溢出。 沒有解釋的評論是一個可怕的想法。 – tony 2010-03-08 21:32:49

0

您需要與陣列一起傳遞的大小,就像它在許多庫函數進行,例如strncpy()strncmp()等對不起,這只是它在C :-)中的工作方式。

或者,也可以推出自己的結構類似:

struct array { 
    int* data; 
    int size; 
}; 

,並通過它在你的代碼。

如果你想成爲更多的C++ -ish,當然你仍然可以使用std::liststd::vector

4

在GNU的libstdc提及的common idiom ++文檔是lengthof功能:

template<typename T, unsigned int sz> 
inline unsigned int lengthof(T (&)[sz]) { return sz; } 

你可以使用它作爲

int x[] = {1,2,3,4,5}; 
std::cerr << lengthof(x) << std::endl; 

警告:數組有沒有decayed into a pointer只有當這會工作。

1

數組表達式將其類型從「T的N元素數組」隱式轉換爲「指向T的指針」,其值將是數組中第一個元素的地址,除非數組表達式是操作數sizeof或address-of(&)操作符,或者如果數組表達式是用於在聲明中初始化另一個數組的字符串文字。簡而言之,您不能將數組作爲作爲數組傳遞給函數;函數收到的是一個指針值,而不是數組值。

您必須將數組大小作爲單獨的參數傳遞。

由於您使用的是C++,因此使用矢量(或其他合適的STL容器)而不是C風格的數組。是的,你失去了方便的簡化語法,但折衷不僅僅是值得的。認真。

2

我也同意Corwin的方法非常好。

template <int N> 
void foo(int (&x)[N]) 
{ 
    std::cerr << N; 
} 

我不認爲有人給出了一個很好的理由,爲什麼這不是一個好主意。
在java中,例如,我們可以寫的東西,如:

int numbers [] = {1, 2, 3, 4}; 
for(int i = 0; i < numbers.length(); i++) 
{ 
    System.out.println(numbers[i]+"\n"); 
} 

在C++中這將是很好的,而不是說

int numbers [] = {1, 2, 3, 4}; 
int size = sizeof(numbers)/sizeof(int); 
for(int i = 0; i < size; i++) 
{ 
    cout << numbers[i] << endl; 
} 

我們可以採取這一步,去

template <int N> 
int size(int (&X)[N]) 
{ 
    return N; 
} 

或者,如果這會導致問題,我想你可以明確地寫:

template < int N > 
int size(int (&X)[N]) 
{ 
    int value = (sizeof(X)/sizeof(X[0])); 
    return value; 
} 

那麼我們只需要在主走:

int numbers [] = {1, 2, 3, 4}; 
for(int i = 0; i < size(numbers); i++) 
{ 
    cout << numbers[i] << endl; 
} 

對我來說很有意義:-)

0

由於C++ 11,有一個很方便的方法:

static const int array[] = { 1, 2, 3, 6 }; 
int size = (int)std::distance(std::begin(array), std::end(array))+1;