使用 %d 打印 unsigned long long
为什么我打印以下内容时得到-1?
unsigned long long int largestIntegerInC = 18446744073709551615LL;
printf ("largestIntegerInC = %d\n", largestIntegerInC);
我知道我应该使用 llu
而不是 d
,但为什么我得到 -1 而不是 18446744073709551615LL?
是因为溢出吗?
Why do I get -1 when I print the following?
unsigned long long int largestIntegerInC = 18446744073709551615LL;
printf ("largestIntegerInC = %d\n", largestIntegerInC);
I know I should use llu
instead of d
, but why do I get -1 instead of 18446744073709551615LL?
Is it because of overflow?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
在二进制补码算术中,有符号值 -1 与最大无符号值相同。
考虑二进制补码中负数的位模式(我使用的是 8 位整数,但无论大小如何,该模式都适用):
因此,您可以看到负 1 具有全 1 的位模式,这也是位模式为最大的无符号值。
In two's complement arithmetic, the signed value -1 is the same as the largest unsigned value.
Consider the bit patterns for negative numbers in two's complement (I'm using 8 bit integers, but the pattern applies regardless of the size):
So, you can see that negative 1 has the bit pattern of all 1's which is also the bit pattern for the largest unsigned value.
您使用了带符号的 32 位数字的格式,因此得到 -1。
printf()
无法在内部判断您传入的数字有多大,因此它只是从可变参数列表中提取前 32 位,并将它们用作要打印出来的值。由于您提供了带符号的格式,因此它会以这种方式打印它,并且 0xffffffff 是 -1 的二进制补码表示形式。You used a format for a signed 32-bit number, so you got -1.
printf()
can't tell internally how big the number you passed in is, so it just pulls the first 32 bits from the varargs list and uses them as the value to be printed out. Since you gave a signed format, it prints it that way, and 0xffffffff is the two's complement representation of -1.您可以(应该)在编译器警告中看到原因。如果不是,请尝试设置最高警告级别。使用 VS,我收到此警告:警告 C4245:'初始化':从 '__int64' 到 'unsigned __int64' 的转换,有符号/无符号不匹配。
You can (should) see why in compiler warning. If not, try to set the highest warning level. With VS I've got this warning: warning C4245: 'initializing' : conversion from '__int64' to 'unsigned __int64', signed/unsigned mismatch.
不,没有溢出。这是因为它没有打印整个值:
18446744073709551615 与 0xFFFFFFFFFFFFFFFF 相同。当 printf %d 处理该数据时,它仅获取 32 位(如果是 64 位 CPU,则获取 64 位)进行转换,这些是有符号值 -1。
如果
printf
转换为%u
,则它将显示 4294967295(32 位)或 18446744073709551615(64 位)。溢出是指值增加到无法容纳分配的存储空间的程度。在这种情况下,该值已分配,但未完全检索。
No, there is no overflow. It's because it isn't printing the entire value:
18446744073709551615 is the same as 0xFFFFFFFFFFFFFFFF. When
printf %d
processes that, it grabs only 32 bits (or 64 bits if it's a 64-bit CPU) for conversion, and those are the signed value -1.If the
printf
conversion had been%u
instead, it would show either 4294967295 (32 bits) or 18446744073709551615 (64 bits).An overflow is when a value increases to the point where it won't fit in the storage allocated. In this case, the value is allocated just fine, but isn't being completely retrieved.
在 C (99) 中,
LLONG_MAX
保证long long int
类型的最大值至少为9223372036854775807
。unsigned long long int
的最大值保证至少为18446744073709551615
,即 264−1 (0xffffffffffffffff< /代码>)。
因此,初始化应该是:(
注意
ULL
。)由于largestIntegerInC
是unsigned long long int
类型,因此您应该使用正确的方式打印它格式说明符,即"%llu"
:上面的第二个
printf()
是错误的,它可以打印任何内容。您正在使用"%d"
,这意味着printf()
需要一个int
,但得到一个unsigned long long int< /code>,(很可能)与
int
的大小不同。您得到-1
作为输出的原因是由于(坏)运气,并且事实上,在您的机器上,数字是使用二进制补码表示形式来表示的。为了看看这有多糟糕,让我们运行以下程序:
在我的 Macbook 上,使用
"%d %d %d"
运行该程序会得到-1 -1 42
,在 Linux 机器上,具有相同格式的相同程序给出-1 42 -1
。哎呀。事实上,如果您尝试在
largestIntegerInC
变量中存储最大的unsigned long long int
数字,您应该包含limits.h
并使用ULLONG_MAX
。或者您应该将-1
存储到您的变量中:在上面的程序中,
largestIntegerInC
和next
都包含的最大可能值unsigned long long int
类型。In C (99),
LLONG_MAX
, the maximum value oflong long int
type is guaranteed to be at least9223372036854775807
. The maximum value of anunsigned long long int
is guaranteed to be at least18446744073709551615
, which is 264−1 (0xffffffffffffffff
).So, initialization should be:
(Note the
ULL
.) SincelargestIntegerInC
is of typeunsigned long long int
, you should print it with the right format specifier, which is"%llu"
:The second
printf()
above is wrong, it can print anything. You are using"%d"
, which meansprintf()
is expecting anint
, but gets aunsigned long long int
, which is (most likely) not the same size asint
. The reason you are getting-1
as your output is due to (bad) luck, and the fact that on your machine, numbers are represented using two's complement representation.To see how this can be bad, let's run the following program:
On my Macbook, running the program with
"%d %d %d"
gives me-1 -1 42
, and on a Linux machine, the same program with the same format gives me-1 42 -1
. Oops.In fact, if you are trying to store the largest
unsigned long long int
number in yourlargestIntegerInC
variable, you should includelimits.h
and useULLONG_MAX
. Or you should store assing-1
to your variable:In the above program, both
largestIntegerInC
andnext
contain the largest possible value forunsigned long long int
type.这是因为您传递的数字的所有位都设置为 1。当解释为二进制补码有符号数字时,结果为 -1。在这种情况下,它可能只查看其中的 32 位,而不是全部 64 位,但这并没有任何真正的区别。
It's because you're passing a number with all the bits set to 1. When interpreted as a two's complement signed number, that works out to -1. In this case, it's probably only looking at 32 of those one bits instead of all 64, but that doesn't make any real difference.