这个表达式是评估2 ^ x的一种方法(我知道这种方法的危险性):
2 << (x-1)
替换x = 0并且表达式给出了所需的结果1.但是当它放在一个函数中时,它总是返回0:
int fast_2_to_the(int x) {
return 2 << (x-1);
}
这可以在这个程序中观察到:
int main(int argc, char *argv[]) {
printf("2 << (0-1) = %d\n", 2 << (0-1));
printf("fast_2_to_the(0) = %d\n", fast_2_to_the(0));
return 0;
}
其中给出了以下输出:
2&lt;&lt; (0-1)= 1
fast_2_to_the(0)= 0
为什么会这样?我是C的初学者,最近一直在学习按位运算符,所以任何相关的建议都会受到赞赏。
答案 0 :(得分:6)
根据C99§6.5.7¶3,具有负右操作数的位移是未定义的行为。这意味着编译器可以自由发出可能无法正常工作的代码,以防你有负移位(或者,根据关于未定义行为的通常规则,它也可能使恶魔飞出你的鼻子)。
正如评论中所建议的那样,执行该转换的正确方法是1 << x
,只要结果不超出int
的范围,该方法就可以正常工作。
答案 1 :(得分:3)
根据每个C标准,从古老的C89到C11,你所经历的是未定义的行为。
来自N1570(C11草案)6.5.7/3
按位移位运算符:
对每个操作数执行整数提升。类型 结果是提升左操作数的结果。如果值 右操作数为负或大于或等于宽度 升级后的左操作数,行为未定义。