C 正在使用%d打印未签名的长文件
为什么打印以下内容时得到-1C 正在使用%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位整数
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;
}