以下代码仅要求输入数字num
,然后要求输入该数字的一点tbit
,以进行切换/反转,然后输出新的数字ans
。
在Debian 9上将Geany与gcc编译器版本6.3.0 20170516配合使用,当我执行以下代码时,得到的答案为ans
为6,而当我期望编译器或运行时错误告诉我:米超出范围。
使用此版本的gcc,sizeof(int)
返回四个字节或32位。当我尝试切换第100位时,ans=6
会发生什么?
示例输入:
Enter a number : 22
Enter the bit you want to toggle : 100
输出:
The number you entered is 22
after toggling the 100 bit
the new number is 6.`
代码:
#include <stdio.h>
int main ()
{
int num, tbit, tool = 1, ans;
printf(Enter a number :");
scanf("%d", &num);
printf(Enter the bit you want to toggle :");
scanf("%d", &tbit);
ans = (tool<<tbit) ^ num;
printf("The number you entered is %d after toggling the %d bit the new
number is %d\n" , num, tbit, ans);
return 0;
}
答案 0 :(得分:4)
C没有“运行时错误”之类的东西。在表达式x<<n
中,如果n
的值超过了x
的(提升的)类型的宽度,或者该类型是带符号的并且结果将溢出,则行为未定义。这意味着该语言对发生的事情没有任何要求,这可能是很奇怪和意外的事情。
相关文本为 6.5.7按位移位运算符,¶3:
对每个操作数执行整数提升。结果的类型是提升后的左操作数的类型。如果右操作数的值为负或大于或等于提升的左操作数的宽度,则行为是不确定的。
答案 1 :(得分:2)
根据C语言标准,行为未定义:
6.5.7.3:如果右操作数的值为负或为 大于或等于提升的左操作数的宽度,则行为是不确定的。
在每种特定情况下发生的事情都取决于硬件,因此任何依赖于此的程序都是无效的。在您的情况下,似乎硬件会截断tbit
的高位,就像代码如下所示:
ans = (tool<< (tbit & 0x1F)) ^ num;
这是X86 CPU常见的行为:
Intel的手册]指出,当
cnt
大于操作数大小时,结果是不确定的,但是至少对于32位和64位数据大小,已经观察到{{1 }},其中(cnt mod n)
是数据大小(source)。