C++ 中数组的元素计数

发布于 2024-10-15 02:21:24 字数 227 浏览 6 评论 0原文

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

我只能处理一种情况:数组包含属于数组类型的不同派生类型的元素。

我是对的吗?还有(我几乎肯定一定有)其他类似的情况吗?

抱歉问这个小问题,我是一名 Java 开发人员,而且对 C++ 还很陌生。

谢谢!

Let's say I have an array arr. When would the following not give the number of elements of the array: sizeof(arr) / sizeof(arr[0])?

I can thing of only one case: the array contains elements that are of different derived types of the type of the array.

Am I right and are there (I am almost positive there must be) other such cases?

Sorry for the trivial question, I am a Java dev and I am rather new to C++.

Thanks!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(14

倒带 2024-10-22 02:21:25

从 C++17 开始,您还可以使用标准化的自由函数:
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

Since C++17 you can also use the standardized free function:
std::size(container) which will return the amount of elements in that container.

example:

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
葬花如无物 2024-10-22 02:21:25

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

如果在声明中定义了大小,则仅在编译时才知道该信息:

char array[256];

在这种情况下,sizeof(array) 为您提供正确的大小。

但是,如果您使用指针作为数组,则“数组”将只是一个指针,并且 sizeof 不会为您提供有关数组实际大小的任何信息。

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

Arrays in C++ are very different from those in Java in that they are completely unmanaged. The compiler or run-time have no idea whatsoever what size the array is.

The information is only known at compile-time if the size is defined in the declaration:

char array[256];

In this case, sizeof(array) gives you the proper size.

If you use a pointer as an array however, the "array" will just be a pointer, and sizeof will not give you any information about the actual size of the array.

STL offers a lot of templates that allow you to have arrays, some of them with size information, some of them with variable sizes, and most of them with good accessors and bounds checking.

一梦浮鱼 2024-10-22 02:21:25

给定一个数组arr,在任何情况下,sizeof(arr) / sizeof(arr[0]) 的值都不是元素的计数,通过数组和sizeof的定义。

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

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

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

There are no cases where, given an array arr, that the value of sizeof(arr) / sizeof(arr[0]) is not the count of elements, by the definition of array and sizeof.

In fact, it's even directly mentioned (§5.3.3/2):

.... When applied to an array, the result is the total number of bytes in the array. This implies that the size of an array of n elements is n times the size of an element.

Emphasis mine. Divide by the size of an element, sizeof(arr[0]), to obtain n.

带刺的爱情 2024-10-22 02:21:25

不,这仍然会产生正确的值,因为您必须将数组定义为单一类型的所有元素或指向类型的指针。无论哪种情况,数组大小在编译时都是已知的,因此 sizeof(arr) / sizeof(arr[0]) 始终返回元素计数。

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

int nonDynamicArray[ 4 ];

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

我将在此处进一步说明何时正确使用此功能。你不会经常使用它。当您想要专门定义一个数组时,它非常有用,这样您就可以向其中添加元素,而无需稍后更改大量代码。它是一个主要用于维护的结构。典型的例子(无论如何,当我想到它时;-)正在为某个程序构建一个命令表,您打算稍后添加更多命令。在此示例中,要维护/改进您的程序,您所需要做的就是向数组添加另一个命令,然后添加命令处理程序:

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)
    }
}

No that would still produce the right value because you must define the array to be either all elements of a single type or pointers to a type. In either case the array size is known at compile time so sizeof(arr) / sizeof(arr[0]) always returns the element count.

Here is an example of how to use this correctly:

int nonDynamicArray[ 4 ];

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

I'll go one further here to show when to use this properly. You won't use it very often. It is primarily useful when you want to define an array specifically so you can add elements to it without changing a lot of code later. It is a construct that is primarily useful for maintenance. The canonical example (when I think about it anyway ;-) is building a table of commands for some program that you intend to add more commands to later. In this example to maintain/improve your program all you need to do is add another command to the array and then add the command handler:

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)
    }
}
请恋爱 2024-10-22 02:21:25

MSVC 中的 _countof(my_array)

我只能处理一种情况:数组包含属于数组类型的不同派生类型的元素。

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

正如上面提到的, sizeof(my_array) (也像 _countof() )将仅在数组定义的范围内工作。

_countof(my_array) in MSVC

I can thing of only one case: the array contains elements that are of different derived types of the type of the array.

Elements of an array in C++ are objects, not pointers, so you cannot have derived type object as an element.

And like mentioned above, sizeof(my_array) (like _countof() as well) will work just in the scope of array definition.

小傻瓜 2024-10-22 02:21:25

First off, you can circumvent that problem by using std::vector instead of an array. Second, if you put objects of a derived class into an array of a super class, you will experience slicing, but the good news is, your formula will work. Polymorphic collections in C++ are achieved using pointers. There are three major options here:

寻找我们的幸福 2024-10-22 02:21:25

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

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

我只能处理一种情况:数组包含属于数组类型的不同派生类型的元素。

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

抱歉问了这个小问题,我是一名 Java 开发人员,而且对 C++ 还很陌生。

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

Let's say I have an array arr. When would the following not give the number of elements of the array: sizeof(arr) / sizeof(arr[0])?

In contexts where arr is not actually the array (but instead a pointer to the initial element). Other answers explain how this happens.

I can thing of only one case: the array contains elements that are of different derived types of the type of the array.

This cannot happen (for, fundamentally, the same reason that Java arrays don't play nicely with generics). The array is statically typed; it reserves "slots" of memory that are sized for a specific type (the base type).

Sorry for the trivial question, I am a Java dev and I am rather new to C++.

C++ arrays are not first-class objects. You can use boost::array to make them behave more like Java arrays, but keep in mind that you will still have value semantics rather than reference semantics, just like with everything else. (In particular, this means that you cannot really declare a variable of type analogous to Foo[] in Java, nor replace an array with another one of a different size; the array size is a part of the type.) Use .size() with this class where you would use .length in Java. (It also supplies iterators that provide the usual interface for C++ iterators.)

梦途 2024-10-22 02:21:25

使用 Microsoft“_countof(array)”宏。 Microsoft Developer Network 的链接对此进行了解释,并提供了一个示例来演示“sizeof(array)”和“_countof(array)”宏之间的区别。

Microsoft 和“_countof(array)”宏

Use the Microsoft "_countof(array)" Macro. This link to the Microsoft Developer Network explains it and offers an example that demonstrates the difference between "sizeof(array)" and the "_countof(array)" macro.

Microsoft and the "_countof(array)" Macro

甜心小果奶 2024-10-22 02:21:25

看来,如果您知道数组中元素的类型,您也可以通过 sizeof 来利用它。

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

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

// => 5

It seems that if you know the type of elements in the array you can also use that to your advantage with sizeof.

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

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

// => 5
弃爱 2024-10-22 02:21:25

如果您不能使用允许使用 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

If you can not use C++17, which allows to use std::size(container), you can easily implement your own generic sizeofArray template function as a one-liner:

#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" );
}

test it here: http://cpp.sh/8tio3

睫毛溺水了 2024-10-22 02:21:25

当且仅当 arr 是一个 C 数组(type[size];函数参数除外!)、对 C 数组的引用(>type(&)[size]) 或指向 C 数组的指针 (type(*)[size])。

注意对于当前的 C++ 标准,您应该使用 std::sizestd::ssize 来代替

C++17中,您可以使用std::size

int arr[] = {1, 2, 3};
auto count = std::size(arr); // type std::size_t, value == 3

C++20中,您可以另外获得使用 std::ssize 得到有符号值

int arr[] = {1, 2, 3};
auto count = std::ssize(arr); // type std::ptrdiff_t, value == 3

另请注意,C++ 不幸地从 C 继承,C 数组永远不会按值(深层复制)传递给函数。

void f(int a[3]);

与此相同,

void f(int* a);

因此您会丢失 a 是一个数组以及它有多少元素的信息。 3 被编译器完全忽略!

如果要保留数据类型(包括数组元素计数),可以使用指针或对 C 数组的引用:

void f(int (&a)[3]); // reference to C-Array with 3 elements
void f(int (*a)[3]); // pointer to C-Array with 3 elements
void f(int a[3]);    // pointer to int
void f(int* a);      // pointer to int

如果要使用数组按值调用来调用函数,可以使用 C++ 数组( std::array) 来自 C++ 标准库:

f(std::array<int, 3> a);

std::array<int, 3> arr = {1, 2, 3};
f(arr); // deep copy

It will work if and only if arr is a C-Array (type[size]; except for function parameters!), a reference to a C-Array (type(&)[size]) or a pointer to a C-Array (type(*)[size]).

Note you should use std::size or std::ssize instead with current C++-Standards!

In C++17 you can use std::size:

int arr[] = {1, 2, 3};
auto count = std::size(arr); // type std::size_t, value == 3

In C++20 you can additionally get a signed value by using std::ssize:

int arr[] = {1, 2, 3};
auto count = std::ssize(arr); // type std::ptrdiff_t, value == 3

Also note that C++ unfortunately inherited from C that C-Arrays are never passed by value (deep copy) to functions.

void f(int a[3]);

is the same as

void f(int* a);

so you loose the information that a is an array and with this, how much elements it had. The 3 is completely ignored by the compiler!

If you want to preserve the datatype (including the array element count), you can use a pointer or a reference to an C-Array:

void f(int (&a)[3]); // reference to C-Array with 3 elements
void f(int (*a)[3]); // pointer to C-Array with 3 elements
void f(int a[3]);    // pointer to int
void f(int* a);      // pointer to int

If you want to call functions with Arrays call-by-value, you can use C++-Arrays (std::array) from the C++ standard library:

f(std::array<int, 3> a);

std::array<int, 3> arr = {1, 2, 3};
f(arr); // deep copy
宛菡 2024-10-22 02:21:25

确定数组中有多少个数字。

#include<bits/stdc++.h>
using namespace std;
int main()
{
    int n[10]  ;

    int l = sizeof(n)/sizeof(n[0]);

    cout << l;

    return 0;
}

Determine how many numbers are in your array.

#include<bits/stdc++.h>
using namespace std;
int main()
{
    int n[10]  ;

    int l = sizeof(n)/sizeof(n[0]);

    cout << l;

    return 0;
}
一张白纸 2024-10-22 02:21:25

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

int function count(array[]) {

    int i = 0;

    while(array[i] != NULL) {

        i++;

    }

    return i;

}

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

I know is old topic but what about simple solution like while loop?

int function count(array[]) {

    int i = 0;

    while(array[i] != NULL) {

        i++;

    }

    return i;

}

I know that is slower than sizeof() but this is another example of array count.

匿名。 2024-10-22 02:21:24

假设我有一个数组 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)将给出<的大小em>指针,而不是数组!


编辑:

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

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!

Let's say I have an array arr. When
would the following not give the
number of elements of the array:
sizeof(arr) / sizeof(arr[0])?

One thing I've often seen new programmers doing this:

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

Sample arr[10];
f(arr);

So new programmers think the value of count will be 10. But that's wrong.

Even this is wrong:

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

It's all because once you pass an array to any of these functions, it becomes pointer type, and so sizeof(arr) would give the size of pointer, not array!


EDIT:

The following is an elegant way you can pass an array to a function, without letting it to decay into pointer type:

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!
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文