C++:数组长度的sizeof方法

4

假设我有一个名为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**

1
可能是重复的问题,关于如何找到指向数组的指针的大小。这里有一个相关的问题:如何找到指向数组的指针的大小(也许还有更好的匹配;这是我在快速搜索中找到的最佳匹配)。 - James McNellis
5
дҪ еҸҜиғҪйңҖиҰҒдҪҝз”Ёstd::vector<std::wstring>>жҲ–зұ»дјјзҡ„дёңиҘҝгҖӮиҝҷжҳҜC++пјҢдёҚжҳҜCгҖӮ - fredoverflow
5个回答

12
因为这里的str是指向指针的指针,而不是数组。
这是指针和数组之间微妙差别之一:在这种情况下,你的指针在堆栈上,它指向已经在其他地方(可能是堆)分配的23个字符的数组。

11
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;
}

0
你写道:
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);

0

正如其他人所指出的那样,如果传递给宏的是指针而不是实际数组,则该宏无法正常工作。不幸的是,因为在大多数表达式中指针和数组的计算方式相似,所以除非你让宏变得更加复杂,否则编译器无法让你知道存在问题。

对于 C++ 版本的宏,它是类型安全的(如果您传递了指针而不是数组类型,则会生成错误),请参见:

这并不能完全“修复”您的问题,但它可以让您知道您正在做一些错误的事情。

对于在 C 中工作且相对安全的宏(许多指针将被诊断为错误,但有些将通过而没有错误 - 包括您的指针,不幸的是):

当然,利用#ifdef __cplusplus的能力,你可以在通用头文件中同时拥有这两种定义,并让编译器在C++构建时选择更安全的选项,在没有C++支持的情况下选择C兼容的选项。

0
问题在于 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。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接