使用 %d 打印 unsigned long long

发布于 2024-08-21 20:55:58 字数 281 浏览 5 评论 0原文

为什么我打印以下内容时得到-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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

标点 2024-08-28 20:55:59

在二进制补码算术中,有符号值 -1 与最大无符号值相同。

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

 0 - 0x00
-1 - 0xFF
-2 - 0xFE
-3 - 0xFD

因此,您可以看到负 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):

 0 - 0x00
-1 - 0xFF
-2 - 0xFE
-3 - 0xFD

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.

无声无音无过去 2024-08-28 20:55:59

您使用了带符号的 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.

无人问我粥可暖 2024-08-28 20:55:59

您可以(应该)在编译器警告中看到原因。如果不是,请尝试设置最高警告级别。使用 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.

多情出卖 2024-08-28 20:55:59

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

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.

↘紸啶 2024-08-28 20:55:58

在 C (99) 中,LLONG_MAX 保证 long long int 类型的最大值至少为 9223372036854775807unsigned long long int 的最大值保证至少为 18446744073709551615,即 264−1 (0xffffffffffffffff< /代码>)。

因此,初始化应该是:(

unsigned long long int largestIntegerInC = 18446744073709551615ULL;

注意 ULL。)由于 largestIntegerInCunsigned long long int 类型,因此您应该使用正确的方式打印它格式说明符,即"%llu"

$ 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’

上面的第二个printf()是错误的,它可以打印任何内容。您正在使用 "%d",这意味着 printf() 需要一个 int,但得到一个 unsigned long long int< /code>,(很可能)与 int 的大小不同。您得到 -1 作为输出的原因是由于(坏)运气,并且事实上,在您的机器上,数字是使用二进制补码表示形式来表示的。


为了看看这有多糟糕,让我们运行以下程序:

#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;
}

在我的 Macbook 上,使用 "%d %d %d" 运行该程序会得到 -1 -1 42,在 Linux 机器上,具有相同格式的相同程序给出 -1 42 -1。哎呀。


事实上,如果您尝试在 largestIntegerInC 变量中存储最大的 unsigned long long int 数字,您应该包含 limits.h 并使用ULLONG_MAX。或者您应该将 -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;
}

在上面的程序中,largestIntegerInCnext 都包含 的最大可能值unsigned long long int 类型。

In C (99), LLONG_MAX, the maximum value of long long int type is guaranteed to be at least 9223372036854775807. The maximum value of an unsigned long long int is guaranteed to be at least 18446744073709551615, which is 264−1 (0xffffffffffffffff).

So, initialization should be:

unsigned long long int largestIntegerInC = 18446744073709551615ULL;

(Note the ULL.) Since largestIntegerInC is of type unsigned long long int, you should print it with the right format specifier, which is "%llu":

$ 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’

The second printf() above is wrong, it can print anything. You are using "%d", which means printf() is expecting an int, but gets a unsigned long long int, which is (most likely) not the same size as int. 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:

#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;
}

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 your largestIntegerInC variable, you should include limits.h and use ULLONG_MAX. Or you should store assing -1 to your variable:

#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;
}

In the above program, both largestIntegerInC and next contain the largest possible value for unsigned 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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文