[英]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.