2010-09-03 39 views
3

我想補充編譯時斷言到下面的C++代碼(編譯使用Visual C++ 9):如何在編譯時測試常量是否適合類型?

//assumes typedef unsigned char BYTE; 
int value = ...; 
// Does it fit into BYTE? 
if(0 <= value && value <= UCHAR_MAX) { 
    BYTE asByte = static_cast<BYTE>(value); 
    //proceed with byte 
} else { 
    //proceed with greater values 
} 

問題是UCHAR_MAX和​​是獨立typedef S和當該代碼被移植它可以發生他們不同步並且代碼將會中斷。所以我想要做這樣的事情:

compileTimeAssert(sizeof(BYTE) == sizeof(UCHAR_MAX)); 

但VC++ 9產生「負標」的錯誤,而在編譯 - sizeof(UCHAR_MAX)恰好是4,而不是1

我如何能實現編譯我想要什麼時間檢查?

回答

2

你可以在編譯時斷言((1 << (sizeof(BYTE)*CHAR_BIT)) - 1) == UCHAR_MAX

(我假設你不問如何做一個靜態斷言 - 有幾種方法,請參閱here

+0

酷。應該是'CHAR_BIT'而不是8。 – sharptooth 2010-09-03 10:36:43

+0

@sharptooth - 更正。 – adamk 2010-09-03 10:39:40

+0

對於'BYTE'這可能是好的,但對於更大的類型不會溢出? – bk1e 2010-09-03 16:05:19

5

比較 '值' 與標準:: numeric_limits < BYTE> :: MAX()代替UCHAR_MAX

+0

您不能在常量表達式中使用'std :: numeric_limits < BYTE > :: max()',這是static_assert實現需要的。 PS我想這並不是真正解決問題的「靜態斷言」部分。 – 2010-09-03 10:46:23

+0

是的。但是,如果您針對std :: numeric_limits < BYTE > :: max()測試'value',則不再需要靜態斷言。 sharptooth希望只有一個靜態斷言來驗證測試的最大值對於BYTE類型是否正確。使用numeric_limits,您不必擔心這一點,因爲它可以保證它會給您正確的最大值。 – usta 2010-09-03 10:51:59

+0

啊,是的,你是對的,在這種情況下編譯斷言是多餘的。 – 2010-09-03 10:55:37

1

但VC++ 9在編譯產生的 「負 標」 錯誤 - 的sizeof(UCHAR_MAX )碰巧是4,而不是1.

有了這篇文章,我沒有回答解決方案,但試圖找到根本原因。

考慮表達

#define MAX 255;

我的理解是,sizeof(MAX) a.k.a (sizeof(255))總是要始終整數的標準2.3.1/2的給定平臺按照給定的規則上的文字大小。只是因爲它是UCHAR_MAX並持有char的最大值並不意味着這樣的名字的大小將是char

大小類型文本整數取決於 其形式價值,後綴。如果它是 是十進制的並且沒有後綴,則它有 這些類型中的第一個,其中 的值可以表示爲:int,long int;如果該值不能爲 表示爲long int,則 行爲未定義。如果它是八進制 或十六進制且沒有後綴,則其 具有其中 其值可以表示的第一種類型:int, unsigned int,long int,unsigned long int。如果後綴爲u或U,則其 類型是 中的第一個類型,其值可以表示爲: unsigned int,unsigned long int。如果 後綴爲l或L,則其類型爲 其中的第一個類型,其中 的值可以表示爲:long int, unsigned long int。如果後綴爲ul,lu,uL,Lu,Ul,lU,UL或LU的後綴爲 ,則其類型爲unsigned long int。

因此,期待它是1需要重新檢查,這似乎是這裏的根本原因。 sizeof(MAX)將僅限於那些其中intchar一樣寬的架構。我不確定有多少這樣的系統真的在那裏。

1

UCHAR_MAX是最大值unsigned charunsigned char的大小總是1個字節。如果您想檢查的​​範圍爲0 .. UCHAR_MAX-(UCHAR_MAX/2+1) ... UCHAR_MAX/2然後簡單地檢查是否sizeof(BYTE) == 1

如果你想檢查是否存在int值適合BYTE然後執行:

if (!(value & ~(BYTE)-1)) ... 
相關問題