切换数据类型为int的第100位会产生意外结果

时间:2018-08-21 19:58:45

标签: c gcc int bit-manipulation toggle

以下代码仅要求输入数字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;
}

2 个答案:

答案 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)。