假设我有一个数组arr
。以下什么时候不会给出数组元素的数量:sizeof(arr) / sizeof(arr[0])
?
我只能说一种情况:数组包含的元素具有不同派生类型的数组。
我是对的并且在那里(我几乎肯定必须)其他此类案件?
对于这个微不足道的问题,我很抱歉,我是Java开发人员,而且我对C ++很陌生。
谢谢!
答案 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 ++中的多态集合。这里有三个主要选择:
boost::shared_ptr
答案 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)”宏之间的区别。
答案 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)
_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()慢,但这是数组计数的另一个例子。