无符号长长resTestBad = 0xffffffff + 1;使用 %llu 打印 0,但 unsigned long long resTestAgain = 0xffffffffff + 1;用 %llu 打印 68719476736

问题描述 投票:0回答:2

我发现了一个Bug,当%llu的(0xffffffff + 1)的打印值为0时,见下面的代码:

unsigned long long resTestBad = 0xffffffff + 1;  // number of f is 8
printf("resTestBad is %llu, sizeof(unsigned long long) is %ld\n", resTestBad, sizeof(unsigned long long));

将输出:

resTestBad is 0, sizeof(unsigned long long) is 8

我认为输出是错误的,应该输出或者说正确的输出:

resTestBad is 4294967296, sizeof(unsigned long long) is 8

但是下面的代码没有问题:

unsigned long long resTestAgain = 0xfffffffff + 1;   // number of f is 8
printf("resTestAgain is %llu, sizeof(unsigned long long) is %ld\n", resTestAgain, sizeof(unsigned long long));

它会输出(我认为是对的):

resTestAgain is 68719476736, sizeof(unsigned long long) is 8

我的.c 文件如下:

#include <stdio.h>
#include <limits.h>
int main(void)
{

    int s = 0xfffe;
    printf("s is %d\n", s);

    unsigned int ww = 0xfffe;
    printf("ww is %d\n", ww);

    unsigned long long resTestOk = 0xfffffffe + 1; 
    printf("resTestOk is %llu, sizeof(unsigned long long) is %ld\n", resTestOk, sizeof(unsigned long long));

    unsigned long long resTestBad = 0xffffffff + 1;  
    printf("resTestBad is %llu, sizeof(unsigned long long) is %ld\n", resTestBad, sizeof(unsigned long long));

    unsigned long long resTestAgain = 0xfffffffff + 1; 
    printf("resTestAgain is %llu, sizeof(unsigned long long) is %ld\n", resTestAgain, sizeof(unsigned long long));

    unsigned long long resA = 4294967295 + 1; 
    printf("resA is %llu, sizeof(unsigned long long) is %ld\n", resA, sizeof(unsigned long long));

    unsigned long long resTestUUU = 0xffffffffffffff + 1; 
    printf("resTestUUU is %llu, sizeof(unsigned long long) is %ld\n", resTestUUU, sizeof(unsigned long long));

    unsigned long long resH = (0xffffffff+1) / 1024 / 1024 / 1024;
    printf("%llu\n", resH);

    unsigned long long resD = (4294967296) / 1024 / 1024 / 1024;
    printf("%llu\n", resD);


    return 0;

}

运行会输出:

s is 65534
ww is 65534
resTestOk is 4294967295, sizeof(unsigned long long) is 8
resTestBad is 0, sizeof(unsigned long long) is 8
resTestAgain is 68719476736, sizeof(unsigned long long) is 8
resA is 4294967296, sizeof(unsigned long long) is 8
resTestUUU is 72057594037927936, sizeof(unsigned long long) is 8
0
4

可能你不相信,我也不相信,所以我录了一个视频来证明我说的。

参见https://imgur.com/a/RAQVPxS

是cpu的Bug还是VMWare Workstation的Bug?我该如何解决?

c cpu vmware
2个回答
0
投票

正如@rici对另一个问题的回答中所解释的那样,无符号类型是十六进制整数文字的候选者。 0xffffffff 适合

unsigned long
,因此其类型为
unsigned long
,根据您的编译器,它是 32 位。然后将
int
1
转换为
unsigned long
进行加法,导致溢出。最后将
unsigned long
0
转换为
unsigned long long
,成为
resTestBad
的初始值。
使用 

0xffffffffULL

强制文字从一开始就为

unsigned long long
(当您添加另一个 

f

时,该值不再适合

unsigned long
,因此文字已经具有类型
long long
并且可以工作。)
    


0
投票

unsigned long long resTestBad = 0xffffffff + 1;

无符号十六进制常量 
0xffffffff

可以用

unsigned int
类型的对象表示。所以它的类型是
unsigned int
。所以在这个表达中
0xffffffff + 1

unsigned int

类型的对象使用算术(整数 由于通常的算术转换,常量

1
也会转换为类型
unsigned int
)。
结果会出现溢出,因为结果可以用 

unsigned int

类型的对象表示。表达式的值为

0
.
至于这个声明

unsigned long long resTestAgain = 0xfffffffff + 1;

则十六进制常量
0xfffffffff

不能用unsigned int类型的对象表示(前提是

sizeof( unsigned int )
不大于
4
)。如果
sizeof( long int )
等于
8
(并且在您的程序中它确实等于
8
),则该常量可以用
long int
类型的对象表示。
所以在这个表达中

0xfffffffff + 1

对于
long int

类型的对象使用算术..并且表达式的结果也可以用这种类型的对象表示。

    

© www.soinside.com 2019 - 2024. All rights reserved.