2010-09-03 56 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)) ... 
相关问题