1215787625 发表于 2023-10-24 23:19:10

小白求助

#include <stdio.h>
void yichu(int i)
{
        int x = 1 << (sizeof(int) * 8 - 1);
        int result = x & i;
       
        if (result == 1)
                printf("发生了高位溢出\n");
        else
                printf("左移和右移的值分别为:%d %d",i<<=1,i>>=1);
}
int main(void)
{
        int i;
       
        printf("请输入一个数:");        scanf("%d",&i);       
        yichu(i);
       
        return 0;
}
求大佬指点为什么输入1000000000000明显溢出的值,却不会打印发生了高位溢出?{:10_254:}

isdkz 发表于 2023-10-24 23:19:38

问题出在这一行代码上:

int result = x & i;


在这里,你使用了位运算符 & 来检查最高位是否为1,以判断是否发生了高位溢出。然而,这个判断是错误的。

1 << (sizeof(int) * 8 - 1) 会将1左移到整型变量的最高位,得到一个负数。在大多数机器上, int 类型是32位的,所以左移31位后的值为-2147483648。而你输入的1000000000000明显比这个值要大,所以最高位肯定是1,但是由于 int 类型的范围限制,它的值会被截断,导致判断结果为0,即没有发生高位溢出。

要正确判断高位溢出,你可以使用无符号整型来存储输入的值,并将判断条件修改为:

unsigned int x = 1 << (sizeof(unsigned int) * 8 - 1);
unsigned int result = x & i;

if (result != 0)
    printf("发生了高位溢出\n");
else
    printf("左移和右移的值分别为:%u %u", i <<= 1, i >>= 1);


这样,就能正确判断高位溢出了。

陶远航 发表于 2023-10-24 23:19:52

在你的代码中,你检查高位溢出的逻辑是使用位运算符&和常数1进行比较。然而,这种方法不能正确地检测到高位溢出。

原因是,你将右移操作符(>>)用于存储有符号整数类型 int 的变量 i。在进行右移操作时,C语言标准规定对有符号整数进行右移,结果取决于具体的实现。可能会发生算术右移,也可能会发生逻辑右移。在算术右移中,最高有效位(即符号位)的值会保持不变,而在逻辑右移中,最高有效位会被填充为零。

因此,当输入一个大于等于1000000000000的数时,右移操作不会引起高位溢出,因为最高有效位仍然为1。

要正确检测有符号整数的高位溢出,可以使用无符号整数类型 unsigned int 来执行位操作,并将结果与0x80000000(32位系统上的INT_MIN)进行比较。以下是修改后的代码示例:

#include <stdio.h>

void yichu(unsigned int i) {
    unsigned int x = 1U << (sizeof(unsigned int) * 8 - 1);
    unsigned int result = x & i;

    if (result != 0)
      printf("发生了高位溢出\n");
    else
      printf("左移和右移的值分别为:%u %u\n", i <<= 1, i >>= 1);
}

int main(void) {
    unsigned int i;

    printf("请输入一个数:");
    scanf("%u", &i);
    yichu(i);

    return 0;
}


这样修改后的代码会正确检测到输入大于等于1000000000000的数时的高位溢出。
请注意,本回答来自GPT-4
如果问题已经解决,请设置最佳答案
页: [1]
查看完整版本: 小白求助