[英]C++: sizeof for array length
Let's say I have a macro called LengthOf(array)
: 假设我有一个名为LengthOf(array)
的宏:
sizeof array / sizeof array[0]
When I make a new array of size 23, shouldn't I get 23 back for LengthOf
? 当我制作一个新的大小为23的数组时,是否应该为LengthOf
取回23?
WCHAR* str = new WCHAR[23];
str[22] = '\0';
size_t len = LengthOf(str); // len == 4
Why does len == 4
? 为什么len == 4
?
UPDATE : I made a typo, it's a WCHAR*
, not a WCHAR**
. 更新 :我打错了,是WCHAR*
,而不是WCHAR**
。
Because str
here is a pointer to a pointer, not an array. 因为这里的str
是指向指针的指针,而不是数组。
This is one of the fine differences between pointers and arrays: in this case, your pointer is on the stack, pointing to the array of 23 characters that has been allocated elsewhere (presumably the heap). 这是指针和数组之间的细微差别之一:在这种情况下, 指针位于堆栈上,指向已分配给其他位置(可能是堆)的23个字符的数组。
WCHAR** str = new WCHAR[23];
First of all, this shouldn't even compile -- it tries to assign a pointer to WCHAR
to a pointer to pointer to WCHAR
. 首先,这甚至不应该编译-它尝试将pointer to WCHAR
的pointer to pointer to WCHAR
分配给pointer to WCHAR
的pointer to pointer to WCHAR
。 The compiler should reject the code based on this mismatch. 编译器应基于此不匹配拒绝代码。
Second, one of the known shortcomings of the sizeof(array)/sizeof(array[0])
macro is that it can and will fail completely when applied to a pointer instead of a real array. 其次, sizeof(array)/sizeof(array[0])
宏的已知缺点之一是,当应用于指针而不是实际数组时,它可能并且将完全失败。 In C++, you can use a template to get code like this rejected: 在C ++中,您可以使用模板来获取拒绝的代码:
#include <iostream>
template <class T, size_t N>
size_t size(T (&x)[N]) {
return N;
}
int main() {
int a[4];
int *b;
b = ::new int[20];
std::cout << size(a); // compiles and prints '4'
// std::cout << size(b); // uncomment this, and the code won't compile.
return 0;
}
As others have pointed out, the macro fails to work properly if a pointer is passed to it instead of an actual array. 正如其他人指出的那样,如果将指针而不是实际数组传递给宏,则宏将无法正常工作。 Unfortunately, because pointers and arrays evaluate similarly in most expressions, the compiler isn't able to let you know there's a problem unless you make you macro somewhat more complex. 不幸的是,由于大多数表达式中的指针和数组的计算结果相似,除非您使宏变得更加复杂,否则编译器无法让您知道存在问题。
For a C++ version of the macro that's typesafe (will generate an error if you pass a pointer rather than an array type), see: 有关类型安全的C ++版本宏(如果传递指针而不是数组类型,将生成错误),请参见:
It wouldn't exactly 'fix' your problem, but it would let you know that you're doing something wrong. 它不能完全“解决”您的问题,但可以让您知道您做错了什么。
For a macro that works in C and is somewhat safer (many pointers will diagnose as an error, but some will pass through without error - including yours, unfortunately): 对于在C中工作并且更安全的宏(许多指针将诊断为错误,但不幸的是,某些指针将通过而不会出错-包括您的指针):
Of course, using the power of #ifdef __cplusplus
you can have both in a general purpose header and have the compiler select the safer one for C++ builds and the C-compatible one when C++ isn't in effect. 当然,使用#ifdef __cplusplus
您既可以在通用标头中使用它,也可以让编译器为C ++构建选择较安全的标头,而在C ++无效时选择与C兼容的标头。
The problem is that the sizeof
operator checks the size of it's argument. 问题是sizeof
运算符检查其参数的大小。 The argument passed in your sample code is WCHAR*
. 您的示例代码中传递的参数是WCHAR*
。 So, the sizeof(WCHAR*) is 4. If you had an array, such as WCHAR foo[23]
, and took sizeof(foo)
, the type passed is WCHAR[23]
, essentially, and would yield sizeof(WCHAR) * 23
. 因此,sizeof(WCHAR *)为4。如果您有一个数组,例如WCHAR foo[23]
,并且采用sizeof(foo)
,则传递的类型实质上是WCHAR[23]
,并且将产生sizeof(WCHAR) * 23
。 Effectively at compile type WCHAR*
and WCHAR[23]
are different types, and while you and I can see that the result of new WCHAR[23]
is functionally equivalent to WCHAR[23]
, in actuality, the return type is WCHAR*
, with absolutely no size information. 实际上,在编译类型上, WCHAR*
和WCHAR[23]
是不同的类型,尽管您和我可以看到new WCHAR[23]
的结果在功能上等效于WCHAR[23]
,但实际上,返回类型是WCHAR*
,绝对没有尺寸信息。
As a corellary, since sizeof(new WCHAR[23])
equals 4 on your platform, you're obviously dealing with an architecture where a pointer is 4 bytes. 作为核心,由于您的平台上的sizeof(new WCHAR[23])
等于4,因此您显然要处理的指针为4个字节的体系结构。 If you built this on an x64 platform, you'd find that sizeof(new WCHAR[23])
will return 8. 如果是在x64平台上构建的,则会发现sizeof(new WCHAR[23])
将返回8。
You wrote: 你写了:
WCHAR* str = new WCHAR[23];
if 23 is meant to be a static value, (not variable in the entire life of your program) it's better use #define or const than just hardcoding 23. 如果23是一个静态值(在程序的整个生命周期中都不是变量),则最好使用#define或const而不是仅对 23进行硬编码 。
#define STR_LENGTH 23
WCHAR* str = new WCHAR[STR_LENGTH];
size_t len = (size_t) STR_LENGTH;
or C++ version 或C ++版本
const int STR_LENGTH = 23;
WCHAR* str = new WCHAR[STR_LENGTH];
size_t len = static_cast<size_t>(STR_LENGTH);
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.