简体   繁体   English

C ++:sizeof用于数组长度

[英]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 WCHARpointer to pointer to WCHAR分配给pointer to WCHARpointer 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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM