C ++中数组的元素计数

时间:2011-01-29 21:42:05

标签: c++ arrays sizeof

假设我有一个数组arr。以下什么时候不会给出数组元素的数量:sizeof(arr) / sizeof(arr[0])

我只能说一种情况:数组包含的元素具有不同派生类型的数组。

我是对的并且在那里(我几乎肯定必须)其他此类案件?

对于这个微不足道的问题,我很抱歉,我是Java开发人员,而且我对C ++很陌生。

谢谢!

12 个答案:

答案 0 :(得分:30)

  

假设我有一个数组arr。什么时候   以下不会给出   数组元素的数量:   sizeof(arr)/ sizeof(arr [0])?

有一件事我经常看到新程序员这样做:

void f(Sample *arr)
{
   int count = sizeof(arr)/sizeof(arr[0]); //what would be count? 10?
}

Sample arr[10];
f(arr);

所以新程序员认为count的价值将是10.但这是错误的。

即使这是错误的:

void g(Sample arr[]) //even more deceptive form!
{
   int count = sizeof(arr)/sizeof(arr[0]); //count would not be 10  
}

这一切都是因为一旦你将一个数组传递给任何这些函数,它就会变成指针类型,因此sizeof(arr)会给出指针的大小,不是阵列!


编辑:

以下是一种优雅的方法,您可以将数组传递给函数,而不会让它衰减为指针类型:

template<size_t N>
void h(Sample (&arr)[N])
{
    size_t count = N; //N is 10, so would be count!
    //you can even do this now:
    //size_t count = sizeof(arr)/sizeof(arr[0]);  it'll return 10!
}
Sample arr[10];
h(arr); //pass : same as before!

答案 1 :(得分:9)

C ++中的数组与Java中的数组完全不同,因为它们完全不受管理。编译器或运行时不知道数组的大小。

只有在声明中定义了大小,才能在编译时知道信息:

char array[256];

在这种情况下,sizeof(数组)可以为您提供合适的大小。

如果你使用指针作为数组,那么“数组”将只是一个指针,而sizeof将不会提供有关数组实际大小的任何信息。

STL提供了许多模板,允许您拥有数组,其中一些包含大小信息,其中一些具有可变大小,并且大多数都具有良好的访问者和边界检查。

答案 2 :(得分:6)

在给定数组arr的情况下,根据数组和sizeof(arr) / sizeof(arr[0])的定义,sizeof的值不是元素数的情况下,没有任何情况。

事实上,它甚至直接提到(§5.3.3/ 2):

  

....当应用于数组时,结果是数组中的总字节数。 这意味着 n 元素数组的大小 n 乘以元素的大小。

强调我的。除以元素sizeof(arr[0])的大小,以获得 n

答案 3 :(得分:4)

否则仍会产生正确的值,因为您必须将数组定义为单个类型的所有元素或指向类型的指针。在任何一种情况下,数组大小在编译时都是已知的,因此sizeof(arr)/ sizeof(arr [0])总是返回元素计数。

以下是如何正确使用此功能的示例:

int nonDynamicArray[ 4 ];

#define nonDynamicArrayElementCount ( sizeof(nonDynamicArray) / sizeof(nonDynamicArray[ 0 ]) )

我将在这里进一步展示何时正确使用它。你不会经常使用它。当您想要专门定义数组时,它非常有用,因此您可以在不更改大量代码的情况下向其中添加元素。它是一个主要用于维护的构造。规范的例子(当我考虑它的时候;-)正在为某些程序构建一个命令表,你打算稍后添加 more 命令。在这个维护/改进程序的示例中,您需要做的就是向数组添加另一个命令,然后添加命令处理程序:

char        *commands[] = {  // <--- note intentional lack of explicit array size
    "open",
    "close",
    "abort",
    "crash"
};

#define kCommandsCount  ( sizeof(commands) / sizeof(commands[ 0 ]) )

void processCommand( char *command ) {
    int i;

    for ( i = 0; i < kCommandsCount; ++i ) {
        // if command == commands[ i ] do something (be sure to compare full string)
    }
}

答案 4 :(得分:1)

首先,您可以使用std::vector而不是数组来规避该问题。其次,如果将派生类的对象放入超类的数组中,您将体验切片,但好消息是,您的公式将起作用。使用指针实现C ++中的多态集合。这里有三个主要选择:

答案 5 :(得分:1)

  

假设我有一个数组arr。以下什么时候不会给出数组元素的数量:sizeof(arr) / sizeof(arr[0])

arr实际上不是数组的上下文中(而是指向初始元素的指针)。其他答案解释了这是如何发生的。

  

我只能说一种情况:数组包含的元素具有不同派生类型的数组。

这不可能发生(因为,从根本上说,与Java数组不能很好地使用泛型的原因相同)。该数组是静态类型的;它保留了为特定类型(基本类型)调整大小的内存“插槽”。

  

对于这个微不足道的问题,我很抱歉,我是Java开发人员,而且我对C ++很陌生。

C ++数组不是第一类对象。您可以使用boost :: array使它们更像Java数组,但请记住,您仍将拥有值语义而不是引用语义,就像其他所有内容一样。 (特别是,这意味着您无法在Java中声明类似于Foo[]的类型变量,也不能将数组替换为另一个不同大小的数组;数组大小是该类型的一部分。)使用{ {1}}使用此类,您将在Java中使用.size()。 (它还提供了为C ++迭代器提供常用接口的迭代器。)

答案 6 :(得分:1)

使用Microsoft“_countof(array)”宏。这个指向Microsoft Developer Network的链接解释了它,并提供了一个示例,演示了“sizeof(array)”和“_countof(array)”宏之间的区别。

Microsoft and the "_countof(array)" Macro

答案 7 :(得分:1)

从C ++ 17开始,您还可以使用标准化的free函数: std::size(container),它将返回该容器中的元素数量。

示例:

std::vector<int> vec = { 1, 2, 3, 4, 8 };
std::cout << std::size(vec) << "\n\n";    // 5

int A[] = {40,10,20};
std::cout << std::size(A) << '\n';      // 3

答案 8 :(得分:0)

MSVC中的

_countof(my_array)

  

我只能说一种情况:数组包含的元素具有不同派生类型的数组。

C ++中数组的元素是对象,而不是指针,因此您不能将派生类型对象作为元素。

如上所述,sizeof(my_array)(如_countof()也可以在数组定义的范围内工作。

答案 9 :(得分:0)

似乎,如果您知道数组中元素的类型,还可以利用sizeof来利用它。

int numList[] = { 0, 1, 2, 3, 4 };

cout << sizeof(numList) / sizeof(int);

// => 5

答案 10 :(得分:0)

如果您不能使用允许使用 std::size(container) 的 C++17,您可以轻松地将自己的通用 sizeofArray 模板函数实现为单行:

#include <cstddef>
#include <cstdio>

template< typename T, std::size_t N >
inline constexpr std::size_t sizeofArray( const T(&)[N] ) noexcept { return N; }

int x[10];
void* y[100]; 
long z[1000];
struct {int x; char y; long z;} s[123];

static_assert( sizeofArray(x) == 10, "error" );
static_assert( sizeofArray(y) == 100, "error" );
static_assert( sizeofArray(z) == 1000, "error" );
static_assert( sizeofArray(s) == 123, "error" );

int main() {
    puts( "ok" );
}

在这里测试:http://cpp.sh/8tio3

答案 11 :(得分:-2)

我知道这是一个古老的主题,但是像while循环这样的简单解决方案呢?

int function count(array[]) {

    int i = 0;

    while(array[i] != NULL) {

        i++;

    }

    return i;

}

我知道它比sizeof()慢,但这是数组计数的另一个例子。