C ++:sizeof表示数组长度

时间:2010-06-07 22:31:14

标签: c++ macros

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

5 个答案:

答案 0 :(得分:12)

因为str这里是指向指针的指针,而不是数组。

这是指针和数组之间的细微差别之一:在这种情况下,您的指针位于堆栈上,指向已在其他位置分配的23个字符的数组(可能是堆)

答案 1 :(得分:11)

WCHAR** str = new WCHAR[23];

首先,这甚至不应该编译 - 它会尝试将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;
}

答案 2 :(得分:0)

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

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

它不会完全“修复”你的问题,但它会让你知道你做错了什么。

对于在C中工作并且更安全的宏(许多指针将诊断为错误,但有些指针会毫无错误地通过 - 不幸的是包括你的指针):

当然,使用#ifdef __cplusplus的强大功能,您可以将它们都放在通用标头中,并让编译器为C ++构建选择更安全的版本,并在C ++不生效时为C兼容版本选择。< / p>

答案 3 :(得分:0)

问题是sizeof运算符检查它的参数大小。您的示例代码中传递的参数为WCHAR*。因此,sizeof(WCHAR *)是4.如果你有一个数组,例如WCHAR foo[23],并取sizeof(foo),那么传递的类型基本上是WCHAR[23],并且会产生{{ 1}}。编译类型sizeof(WCHAR) * 23WCHAR*的有效类型是不同的,虽然您和我可以看到WCHAR[23]的结果在功能上等同于new WCHAR[23],但实际上,返回type为WCHAR[23],绝对没有大小信息。

作为一个项目,由于你的平台上WCHAR*等于4,你显然正在处理指针为4个字节的架构。如果您在x64平台上构建它,则会发现sizeof(new WCHAR[23])将返回8。

答案 4 :(得分: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);