假设我有一个名为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
是指向指针的指针,而不是数组。WCHAR** str = new WCHAR[23];
首先,这段代码本来就不能编译——它试图将一个 WCHAR 指针
赋值给一个 指向 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;
}
WCHAR* str = new WCHAR[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);
正如其他人所指出的那样,如果传递给宏的是指针而不是实际数组,则该宏无法正常工作。不幸的是,因为在大多数表达式中指针和数组的计算方式相似,所以除非你让宏变得更加复杂,否则编译器无法让你知道存在问题。
对于 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。
std::vector<std::wstring>>
жҲ–зұ»дјјзҡ„дёңиҘҝгҖӮиҝҷжҳҜC++пјҢдёҚжҳҜCгҖӮ - fredoverflow