2014-09-02 61 views
4

我是新来的C++编程,我试图获取数组的大小。有人可以解释为什么会发生这种情况吗?我试着运行runnable.com中的代码,结果如图所示。在初始化,未知大小的数组中使用sizeof() - C++

我相信这是不正确的做法。如果可能的话,你能提出任何简单的方法来获得这种数组的大小吗?

#include <iostream> 

using namespace std; 

int main() 
{ 
    int set1[] = {1, 9, 3, 50, 31, 65}; 
    int set234[] = {3, 5, 5}; 

    cout << sizeof(set1) << endl; 
    cout << sizeof(set234) << endl; 

    cout << "When sizeof() return value is divided by 4"<< endl; 
    cout << sizeof(set1)/4 << endl; 
    cout << sizeof(set234)/4 << endl; 

    return 0; 
} 

**************************************************************** 
Output: 
24 
12 
When sizeof() return value is divided by 4 
6 
3 
**************************************************************** 

**编辑:感谢您的回复。 飞走:D

+2

'sizeof(arr)/ sizeof(arr [0])' – bolov 2014-09-02 17:29:13

+2

@NOWA什么不清楚? – 2014-09-02 17:29:17

+0

规范的答案是'sizeof(foo)/ sizeof(foo [0])'。 – 2014-09-02 17:36:15

回答

3

数组的大小等于其所有元素的大小之和。就像在你的例子中你处理int类型的数组那样,你系统中的sizeof(int)等于4,因此第一个数组有6个元素,那么它的大小等于6 * sizeof(int)即24。数组等于3 * sizeof(int)即12。 如果例如系统中的sizeof(int)等于8,那么第一个数组的大小将等于48(6 * sizeof * int)),并且大小第二个数组将等于18(3 * sizeof(int))。

所以,如果你想例如知道有多少元素有一个数组,你可以计算出下面这样的方式

sizeof(YouArray)/sizeof(YourArray[0]) 

sizeof(YouArray)/sizeof(ElementType) 
+1

+1或'sizeof(YourArray)/ sizeof(* YourArray)',以及所有这些(无可争辩的),在'YourArray'是一个简单的指针而不是真正的本地数组时编译。如果使用'std:array <>',如果通过工具链提供的话,那么就会有更多的燃料。 – WhozCraig 2014-09-02 17:45:02

+0

@NOWA这个解决方案有点危险,就好像'YouArray'实际上是一个指针或者带有重载的'[]'的东西,它返回没有任何警告的虚假信息。 – Yakk 2014-09-02 18:46:30

+0

@Yakk在这种情况下,你可以使用标准类std :: extent – 2014-09-02 18:58:07

0

sizeof以字节为单位返回数组的大小,而不是元素。它看起来像在32位系统(或LP64上运行,意味着只有long和指针是64位,但ints仍然是32),因此整数数组中的每个元素都是4个字节。在您的set1中,这是6个元素,即6x4 = 24个字节。

要获取元素的大小,请执行sizeof(set1)/ sizeof(set1 [0])。不过,这对编译时列出元素的数组起作用。但是,如果您只有一个int *,sizeof运算符将返回指针的大小。

+0

我正在64位系统中运行。多谢,伙计。这有帮助。 – NOWA 2014-09-02 17:34:21

+0

噢,呃,可能是LP64,这意味着长和指针是64位的。整数仍然是32位。更新答案来解决这个问题。 – 2014-09-02 17:35:10

0

sizeof()以字节为单位给出总大小。例如,如果int为4,并且数组中有6个元素。它会返回4 * 6 = 24作为答案。因此下面的代码会给你一个数组的大小。

#include <iostream> 

using namespace std; 

int main() 
{ 
    int set1[] = {1, 9, 3, 50, 31, 65}; 
    int set234[] = {3, 5, 5}; 

    cout << (sizeof(set1))/4 << endl; 
    cout << (sizeof(set234))/4 << endl; 


    return 0; 
} 

您也可以使用此:

#include <iostream> 
#include <array> 

int main() 
{ 
    array<int,5> a; 
    cout << "size is" << a.size(); 
return 0; 
} 
+1

不要使用像4这样的幻数。它们不适用于每个平台。 – bolov 2014-09-02 17:33:27

+0

@bolov说什么。改为获取元素do sizeof(set1 [0])的大小。 – 2014-09-02 17:34:07

+0

谢谢,伙计。这有助于:) – NOWA 2014-09-02 17:34:51

1

sizeof返回的字节数,而不是元素的数量。大多数情况下你应该避免数组;使用std::vectorstd::array,都提供了一种获取元素数量的简单方法。

0

要获得元素的计数在堆栈中分配的数组中,通常的方法是获取整个数组的总大小(以字节为单位),然后除以单个数组项的大小(以字节为单位):

<item count> = <total array size in bytes>/<single array item size in bytes> 

然而,该公式可以仅应用于阵列堆栈上分配,到阵列动态在堆上分配(例如使用new[]):在后一种情况下,您需要将数组项计数保存为单独的一条信息。

的Microsoft Visual C++提供了一个方便_countof()宏,即做上述计算为您,并且安全地断裂编译过程,如果该参数是一个指针例如到一个动态分配的数组(因为在这种情况下,上面的公式给出了一个不正确的结果,即指针的大小 - 它是固定的,例如32位系统上的4个字节,与指向的数组大小无关 - 除以第一个指出的项目的大小)。

看起来好像是there is an equivalent safe ARRAY_SIZE() macro for Linux

0
#include <cstddef> 

template<class T, std::size_t N> 
std::size_t length_of(T(&)[N]) { 
    return N; 
} 

是解决您的问题的模板。

在C++ 11具有更高的工业强度的版本是:

#include <array> 

template<class T, std::size_t N> 
constexpr std::size_t size(T(&)[N]) { 
    return N; 
} 
template<class T, std::size_t N> 
constexpr std::size_t size(std::array<T,N> const&) { 
    return N; 
} 
template<class C,class=void> 
struct has_size : std::false_type {}; 
template<class>using void_t=void; 
template<class C, void_t< decltype(std::declval<C&>().size()) > > 
struct has_size : std::true_type {}; 

template<bool b, class T=void>using enable_if_t=typename std::enable_if<b,T>::type; 

template<class C, class=enable_if_t< has_size<C>::value, bool[1] >> 
constexpr std::size_t size(C const& c) { 
    return c.size(); 
} 

template<class C, class=enable_if_t< !has_size<C>::value, bool[2] >> 
constexpr std::size_t size(C const& c) { 
    using std::begin; using std::end; 
    return end(c)-begin(c); 
} 

这可能走得太远。请注意,缺少大小的容器中的非随机访问迭代器可能无法编译(因为通常没有定义-),这种类型在purpoes上(我们不希望意外执行O(n)工作)。

+0

我只是把它称为它的大小。另一个版本(可以适用于所有容器,而不仅仅是C风格的数组)可以使用'return std :: end(array) - std :: begin(array);'(其中'array'是你的名字论据)。为什么标准提供'std :: begin'和'std :: end'而没有提供'std :: size'节拍。 – 2014-09-02 19:11:08

+0

@JamesKanze增加威逼工业强度版本。当有size时,使用'begin' /'end'也是一个坏主意,imho,因为它可能效率更低和/或不起作用(参见'std :: unordered_map',它有一个'size )'但在它的迭代器上没有'operator-')上面的std :: array版本可能是多余的,因为'.size()'已经是'array'的'constexpr'了? – Yakk 2014-09-02 19:31:46

+0

当然,你说得对,如果容器有'尺寸',那就是你应该使用的。但我真正的问题仍然是:为什么它不在标准中?正如你的代码所指出的那样,一个工业强度版本并不是微不足道的,它确实是标准应该提供的东西。 – 2014-09-04 12:53:28

相关问题