切换数据类型 int 的第 100 位会产生意想不到的结果
Toggling 100th bit of data type int gives unexpected results
下面的代码只是请求一个数字 num
,然后是那个数字的 tbit
位到 toggle/invert,然后打印新数字 ans
。
在带有 gcc 编译器版本 6.3.0 20170516 的 debian 9 上使用 Geany,当我执行以下代码时,我得到的答案是 ans
6,而我本以为编译器或运行时错误会告诉我我越界了。
使用此版本的 gcc sizeof(int)
returns 四个字节或 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;
}
C 没有"runtime error" 这样的东西。在表达式 x<<n
中,如果 n
的值超过了 x
的(提升的)类型的宽度,或者如果该类型是有符号的并且结果会溢出,则 行为未定义。这意味着该语言不会对发生的事情强加任何要求,它可能是奇怪的和意想不到的。
相关文本是6.5.7 移位运算符,¶3:
The integer promotions are performed on each of the operands. The type of the result is that of the promoted left operand. If the value of the right operand is negative or is greater than or equal to the width of the promoted left operand, the behavior is undefined.
根据 C 语言标准,行为未定义:
6.5.7.3: If the value of the right operand is negative or is
greater than or equal to the width of the promoted left operand, the behavior is undefined.
在每种特定情况下发生的事情都取决于硬件,因此任何依赖它的程序都是无效的。在您的情况下,硬件似乎截断了 tbit
的高位,就好像代码如下:
ans = (tool<< (tbit & 0x1F)) ^ num;
这是 X86 CPU 的常见行为:
Intel's manual] states that the results are undefined when cnt
is greater than the operand size, but at least for 32- and 64-bit data sizes it has been observed that shift operations are performed by (cnt mod n)
, with n
being the data size (source).
下面的代码只是请求一个数字 num
,然后是那个数字的 tbit
位到 toggle/invert,然后打印新数字 ans
。
在带有 gcc 编译器版本 6.3.0 20170516 的 debian 9 上使用 Geany,当我执行以下代码时,我得到的答案是 ans
6,而我本以为编译器或运行时错误会告诉我我越界了。
使用此版本的 gcc sizeof(int)
returns 四个字节或 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;
}
C 没有"runtime error" 这样的东西。在表达式 x<<n
中,如果 n
的值超过了 x
的(提升的)类型的宽度,或者如果该类型是有符号的并且结果会溢出,则 行为未定义。这意味着该语言不会对发生的事情强加任何要求,它可能是奇怪的和意想不到的。
相关文本是6.5.7 移位运算符,¶3:
The integer promotions are performed on each of the operands. The type of the result is that of the promoted left operand. If the value of the right operand is negative or is greater than or equal to the width of the promoted left operand, the behavior is undefined.
根据 C 语言标准,行为未定义:
6.5.7.3: If the value of the right operand is negative or is greater than or equal to the width of the promoted left operand, the behavior is undefined.
在每种特定情况下发生的事情都取决于硬件,因此任何依赖它的程序都是无效的。在您的情况下,硬件似乎截断了 tbit
的高位,就好像代码如下:
ans = (tool<< (tbit & 0x1F)) ^ num;
这是 X86 CPU 的常见行为:
Intel's manual] states that the results are undefined when
cnt
is greater than the operand size, but at least for 32- and 64-bit data sizes it has been observed that shift operations are performed by(cnt mod n)
, withn
being the data size (source).