[英]C++: sizeof for array length
假设我有一个名为LengthOf(array)
的宏:
sizeof array / sizeof array[0]
当我制作一个新的大小为23的数组时,是否应该为LengthOf
取回23?
WCHAR* str = new WCHAR[23];
str[22] = '\0';
size_t len = LengthOf(str); // len == 4
为什么len == 4
?
更新 :我打错了,是WCHAR*
,而不是WCHAR**
。
因为这里的str
是指向指针的指针,而不是数组。
这是指针和数组之间的细微差别之一:在这种情况下, 指针位于堆栈上,指向已分配给其他位置(可能是堆)的23个字符的数组。
WCHAR** str = new WCHAR[23];
首先,这甚至不应该编译-它尝试将pointer to WCHAR
的pointer to pointer to WCHAR
分配给pointer to WCHAR
的pointer to pointer to WCHAR
。 编译器应基于此不匹配拒绝代码。
其次, sizeof(array)/sizeof(array[0])
宏的已知缺点之一是,当应用于指针而不是实际数组时,它可能并且将完全失败。 在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;
}
正如其他人指出的那样,如果将指针而不是实际数组传递给宏,则宏将无法正常工作。 不幸的是,由于大多数表达式中的指针和数组的计算结果相似,除非您使宏变得更加复杂,否则编译器无法让您知道存在问题。
有关类型安全的C ++版本宏(如果传递指针而不是数组类型,将生成错误),请参见:
它不能完全“解决”您的问题,但可以让您知道您做错了什么。
对于在C中工作并且更安全的宏(许多指针将诊断为错误,但不幸的是,某些指针将通过而不会出错-包括您的指针):
当然,使用#ifdef __cplusplus
您既可以在通用标头中使用它,也可以让编译器为C ++构建选择较安全的标头,而在C ++无效时选择与C兼容的标头。
问题是sizeof
运算符检查其参数的大小。 您的示例代码中传递的参数是WCHAR*
。 因此,sizeof(WCHAR *)为4。如果您有一个数组,例如WCHAR foo[23]
,并且采用sizeof(foo)
,则传递的类型实质上是WCHAR[23]
,并且将产生sizeof(WCHAR) * 23
。 实际上,在编译类型上, WCHAR*
和WCHAR[23]
是不同的类型,尽管您和我可以看到new WCHAR[23]
的结果在功能上等效于WCHAR[23]
,但实际上,返回类型是WCHAR*
,绝对没有尺寸信息。
作为核心,由于您的平台上的sizeof(new WCHAR[23])
等于4,因此您显然要处理的指针为4个字节的体系结构。 如果是在x64平台上构建的,则会发现sizeof(new WCHAR[23])
将返回8。
你写了:
WCHAR* str = new WCHAR[23];
如果23是一个静态值(在程序的整个生命周期中都不是变量),则最好使用#define或const而不是仅对 23进行硬编码 。
#define STR_LENGTH 23
WCHAR* str = new WCHAR[STR_LENGTH];
size_t len = (size_t) STR_LENGTH;
或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.