我有以下代码
char x ='s', y='e';
if((x+(y<<16)) == ('a'+('b'<<16)))
//do something
switch (x+(y<<16)) {
case 'a'+('b'<<16):
//do something
break;
if
在和 中进行的比较中是否有任何铸造问题switch
?
您是否打算将第二个值移位 16 位 *then,然后添加第一个?如果是这样,那么您将遇到问题,因为+
优先级高于<<
以下两个表达式证明了这一点:
'a' + 'c' << 16
'b' + 'b' << 16
评估给了我们:
printf("%X : %X\n", 'a' + 'c' << 16, 'b' + 'b' << 16);
结果是:
C40000 : C40000
这是因为'a'
和'c'
都提升为int
,加法完成,然后左移 16 位。与'b'
和 也是如此'b'
。因为('a' + 'c') == ('b' + 'b')
,结果是一样的。
如果您打算(或假设)这样做:
'a' + ('c' << 16)
'b' + ('b' << 16)
printf("%X : %X\n", 'a' + ('c'<<16), 'b' + ('b'<<16));
结果是:
630061 : 620062
我怀疑这是你想要达到的。如果不是,并且您依赖于当前的评估优先级,那么您可能对您所拥有的一切都很好。
编辑更新以更改问题内容:
本身不应该有铸造问题。所有值都被编译器提升int
为当前编写的评估。如果您打算将结果分配给小于int
您将遇到问题的东西。即使是short
16 位的 a 也不够宽,因为那是您的移位深度。您需要至少 24 位的空间来进行正确的评估,并且您的实现int
可能会同意这一点,除非您在一些半生不熟的嵌入式系统上(我见过奇怪的事情)。
最好加上一些括号以避免运算符优先级问题:
#define MYMACRO(X,Y) ((X)+(Y)<<16)
否则可能会发生意想不到的事情:
switch(MYMACRO(a+1,b+1)) // expands into switch(a+1+b+1<<16)
没有铸造问题。
编译器会将 x + y 提升为 int 并将其左移 16,然后进行整数比较。
为了便于阅读,假设您需要 unsigned int 比较,您可以将其编码如下。
`if(( (unsigned)(x+y)<<16u) == ( (unsigned)('a'+'b')<<16u)) `
看看像这样展开时会发生什么
MYMACRO(1<<2, 2<<3)+1
所以
define MYMACRO(X,Y) X+Y<<16
应该
define MYMACRO(X,Y) ((X)+(Y)<<16)