C 正在使用%d打印未签名的长文件

C 正在使用%d打印未签名的长文件,c,printf,unsigned-long-long-int,C,Printf,Unsigned Long Long Int,为什么打印以下内容时得到-1 unsigned long long int largestIntegerInC = 18446744073709551615LL; printf ("largestIntegerInC = %d\n", largestIntegerInC); 我知道我应该使用llu而不是d,但是为什么我得到-1而不是18446744073709551615LL 是因为溢出吗?在two的补码算法中,有符号值-1与最大的无符号值相同 考虑2的补码中负数的位模式(我使用的是8位整数

为什么打印以下内容时得到-1

unsigned long long int largestIntegerInC = 18446744073709551615LL;

printf ("largestIntegerInC = %d\n", largestIntegerInC);
我知道我应该使用
llu
而不是
d
,但是为什么我得到-1而不是18446744073709551615LL


是因为溢出吗?

在two的补码算法中,有符号值-1与最大的无符号值相同

考虑2的补码中负数的位模式(我使用的是8位整数,但无论大小,该模式都适用):


因此,可以看到负1具有所有1的位模式,这也是最大无符号值的位模式

您对有符号的32位数字使用了一种格式,因此得到了-1
printf()
无法从内部判断传入的数字有多大,因此它只从varargs列表中提取前32位,并将其用作要打印的值。由于您提供了一种有符号的格式,所以它以这种方式打印,0xFFFFFF是-1的两个补码表示形式。

这是因为您传递的是一个所有位都设置为1的数字。当解释为2的补码有符号数时,结果是-1。在本例中,它可能只查看其中的32位,而不是全部64位,但这并没有任何实际区别。

您可以(应该)在编译器警告中了解原因。如果没有,请尝试设置最高警告级别。有了VS,我得到了这个警告:警告C4245:“初始化”:从“\uuu int64”到“unsigned\uu int64”的转换,有符号/无符号不匹配。

在C(99),
LLONG\u MAX
中,
long long int
类型的最大值保证至少是
9223372036854775807
无符号long long int
的最大值保证至少为
18446744073709551615
,即264−1(
0xffffffffffffffff

因此,初始化应该是:

unsigned long long int largestIntegerInC = 18446744073709551615ULL;
(注意
ULL
)由于
largesterinc
类型为
无符号长整型
,因此应使用正确的格式说明符打印它,即
%llu”

在我的Macbook上,用
%d%d”
运行程序会给我
-1-1 42
,在Linux机器上,相同格式的程序会给我
-1 42-1
。哎呀


事实上,如果您试图在
largestIntegerInC
变量中存储最大的
unsigned long long int
数字,则应包括
limits.h
并使用
ULLONG\u MAX
。或者您应该将assing
-1
存储到变量中:

#include <limits.h>
#include <stdio.h>

int main(void)
{
    unsigned long long int largestIntegerInC = ULLONG_MAX;
    unsigned long long int next = -1;
    if (next == largestIntegerInC) puts("OK");
    return 0;
}
#包括
#包括
内部主(空)
{
无符号长整型大整数c=ULLONG_MAX;
无符号长整型next=-1;
如果(next==LARGESTEINTEGERINC)卖出(“OK”);
返回0;
}

在上面的程序中,
largesterinc
next
都包含
无符号长整型
类型的最大可能值。

否,没有溢出。这是因为它没有打印整个值:

18446744073709551615与0xFFFFFFFFFFFFFF相同。当
printf%d
处理该数据时,它只获取32位(如果是64位CPU,则为64位)进行转换,这些是有符号值-1

如果将
printf
转换为
%u
,则它将显示4294967295(32位)或18446744073709551615(64位)


溢出是指某个值增加到无法装入分配的存储的程度。在这种情况下,值分配得很好,但没有被完全检索。

下面的所有答案都只是猜测。这只是一种未定义的行为,任何事情都是允许的。
$ cat test.c
#include <stdio.h>

int main(void)
{
    unsigned long long int largestIntegerInC = 18446744073709551615ULL;
    /* good */
    printf("%llu\n", largestIntegerInC);
    /* bad */
    printf("%d\n", largestIntegerInC);
    return 0;
}
$ gcc  -std=c99 -pedantic test.c
test.c: In function ‘main’:
test.c:9: warning: format ‘%d’ expects type ‘int’, but argument 2 has type ‘long long unsigned int’
#include <stdio.h>
#include <stdlib.h>
#include <limits.h>

int main(int argc, char *argv[])
{
    const char *fmt;
    unsigned long long int x = ULLONG_MAX;
    unsigned long long int y = 42;
    int i = -1;
    if (argc != 2) {
        fprintf(stderr, "Need format string\n");
        return EXIT_FAILURE;
    }
    fmt = argv[1];
    printf(fmt, x, y, i);
    putchar('\n');
    return 0;
}
#include <limits.h>
#include <stdio.h>

int main(void)
{
    unsigned long long int largestIntegerInC = ULLONG_MAX;
    unsigned long long int next = -1;
    if (next == largestIntegerInC) puts("OK");
    return 0;
}