如何使用 printf 格式化 unsigned long long int?

Posted

技术标签:

【中文标题】如何使用 printf 格式化 unsigned long long int?【英文标题】:How do you format an unsigned long long int using printf? 【发布时间】:2010-09-05 09:28:32 【问题描述】:
#include <stdio.h>
int main() 
    unsigned long long int num = 285212672; //FYI: fits in 29 bits
    int normalInt = 5;
    printf("My number is %d bytes wide and its value is %ul. A normal number is %d.\n", sizeof(num), num, normalInt);
    return 0;

输出:

My number is 8 bytes wide and its value is 285212672l. A normal number is 0.

我认为这个意外结果来自打印unsigned long long int。你怎么printf()unsigned long long int

【问题讨论】:

我刚刚用 gcc 编译了你的代码(用 %llu ),输出是正确的。您是否将任何选项传递给编译器? 请注意,samsung bada 的 newlib 似乎不支持 "%lld" : developer.bada.com/forum/… 另见***.com/questions/5140871/sprintf-for-unsigned-int64 我建议使用 stdint.h 并明确说明变量中的位数。我们仍处于 32 位和 64 位架构之间的过渡期,“unsigned long long int”在两者上的含义并不相同。 【参考方案1】:

在 u(无符号)转换中使用 ll (el-el) long-long 修饰符。 (适用于 Windows,GNU)。

printf("%llu", 285212672);

【讨论】:

或者更准确地说是用于 GNU libc,并且不适用于 Microsoft 的 C 运行时。 这不是 Linux/UNIX 的东西,“ll”长度修饰符是在 C99 中添加到标准 C 中的,如果它在“Microsoft C”中不起作用,那是因为它们不是符合标准。 在 VS2008 中为我工作。此外,据我所知,MS C 编译器(当设置为直接编译 C 时)应该在设计上符合 C90 标准; C99 介绍了一些不是所有人都喜欢的东西。 这里要记住的一件事是,如果您将多个long long 参数传递给printf 并为其中一个使用错误格式,例如@987654324 @ 而不是 %lld,那么即使是打印的参数 after 不正确的参数也可能完全关闭(或者甚至可能导致 printf 崩溃)。本质上,变量参数是在没有任何类型信息的情况下传递给 printf 的,所以如果格式字符串不正确,结果是不可预测的。 听到 Herb Sutter 在接受采访时说,微软的客户不需要 C99,所以他们的纯 C 编译器已经冻结在 C90。这适用于编译为 C 的情况。如果编译为 C++,正如上面其他人所指出的,你应该没问题。【参考方案2】:

%d--> 代表int

%u--> 代表unsigned int

%ld--> 代表long intlong

%lu--> 代表unsigned long intlong unsigned intunsigned long

%lld--> 代表long long intlong long

%llu--> 代表unsigned long long intunsigned long long

【讨论】:

【参考方案3】:

您可能想尝试使用 inttypes.h 库,它为您提供类型,例如 int32_tint64_tuint64_t 等。 然后您可以使用它的宏,例如:

uint64_t x;
uint32_t y;

printf("x: %"PRId64", y: %"PRId32"\n", x, y);

这是“保证”不会给您带来与longunsigned long long 等相同的麻烦,因为您不必猜测每种数据类型中有多少位。

【讨论】:

这些PRId64PRId32 宏定义在哪里? @happy_marmoset:它们在inttypes.h中定义 我认为您需要 PRIu64PRIu32 来获取无符号整数。 inttypes.h 是标准的吗?不会是stdint.h吗? 请注意,这些精确宽度类型是可选的,因为有些架构没有这些精确宽度的整数类型。只有leastXfastX 类型(实际上可能比指定的更宽)是强制性的。【参考方案4】:

对于使用 MSVS 的 long long(或 __int64),您应该使用 %I64d:

__int64 a;
time_t b;
...
fprintf(outFile,"%I64d,%I64d\n",a,b);    //I is capital i

【讨论】:

【参考方案5】:

这是因为 %llu 在 Windows 下无法正常工作,并且 %d 无法处理 64 位整数。我建议改用 PRIu64,您会发现它也可以移植到 Linux。

试试这个:

#include <stdio.h>
#include <inttypes.h>

int main() 
    unsigned long long int num = 285212672; //FYI: fits in 29 bits
    int normalInt = 5;
    /* NOTE: PRIu64 is a preprocessor macro and thus should go outside the quoted string. */
    printf("My number is %d bytes wide and its value is %" PRIu64 ". A normal number is %d.\n", sizeof(num), num, normalInt);
    return 0;

输出

My number is 8 bytes wide and its value is 285212672. A normal number is 5.

【讨论】:

+1 用于引用我从未见过的 PRIu64,但这似乎不能移植到 64 位 Linux(至少),因为 PRIu64 扩展为“lu”而不是“llu”。 那为什么不好呢? long 是 64 位 Linux 上的 64 位值,与除 Windows 之外的所有其他操作系统一样。 @BDatRivenhill Linux/Unix 使用 LP64,其中 long 为 64 位 然而,为了使其更便携,请改用int64_t,因为很可能有些实现的 long long 大于 long "%" PRIu64 匹配 uint64_t"%llu" 匹配 unsigned long long。这个答案有"%" PRIu64unsigned long long。当unsigned long long 超过 64 位时,这种方法会为 UB 播种。最好避免。【参考方案6】:

在 Linux 中为 %llu,在 Windows 中为 %I64u

虽然我发现它在 Windows 2000 中不起作用,但那里似乎有一个错误!

【讨论】:

对于 windows,(或至少,对于 windows 的 microsoft C 编译器)还有 %I64d、%I32u 和 %I32d 它与 Windows 2000 有什么关系? C 库是处理 printf 的库。 正是我观察到的。我编写了一个使用这种结构的应用程序,它在 WinXP 上完美运行,但在 Win2k 上吐出垃圾。也许这与 C 库对内核进行的系统调用有关,也许与 Unicode 有关,谁知道呢。我记得必须使用 _i64tot() 或类似的东西来解决它。 Win2k/Win9x 问题可能是由于 unsigned long long 数据类型相对较新(当时采用 C99 标准),但 C 编译器(包括 MinGW/GCC)利用旧的 Microsoft C 运行时仅支持 C89 规范。我只能访问真正古老且相当新的 Windows API 文档。所以很难准确地说出I64u 支持何时加入。但听起来像是XP 时代。【参考方案7】:

用VS2005编译成x64:

%llu 效果很好。

【讨论】:

【参考方案8】:

显然,自 2008 年以来,十多年来没有人提出多平台* 解决方案,所以我将附上我的 ?。请点赞。 (开玩笑。我不在乎。)

解决方案:lltoa()

使用方法:

#include <stdlib.h> /* lltoa() */
// ...
char dummy[255];
printf("Over 4 bytes: %s\n", lltoa(5555555555, dummy, 10));
printf("Another one: %s\n", lltoa(15555555555, dummy, 10));

OP 的例子:

#include <stdio.h>
#include <stdlib.h> /* lltoa() */

int main() 
    unsigned long long int num = 285212672; // fits in 29 bits
    char dummy[255];
    int normalInt = 5;
    printf("My number is %d bytes wide and its value is %s. "
        "A normal number is %d.\n", 
        sizeof(num), lltoa(num, dummy, 10), normalInt);
    return 0;

%lld 打印格式字符串不同,这对我在 Windows 上的 32 位 GCC 下工作。

*) 嗯,几乎是多平台的。在 MSVC 中,您显然需要 _ui64toa() 而不是 lltoa()

【讨论】:

我没有lltoa lltoa() 不是标准 C 库函数。除非允许非标准扩展,否则编译时它在 Windows 上的 32 位 GCC 下不起作用。 sizeof(num) 返回size_t"%d" 没有指定使用它。 "%zu" 更好。【参考方案9】:

除了人们多年前写的:

您可能会在 gcc/mingw 上收到此错误:

main.c:30:3: warning: unknown conversion type character 'l' in format [-Wformat=]

printf("%llu\n", k);

那么你的mingw版本不默认为c99。添加此编译器标志:-std=c99

【讨论】:

【参考方案10】:

如何使用printf 格式化unsigned long long int

从 C99 开始,在转换说明符 o,u,x,X 之前使用 "ll" (ell-ell)。

许多答案中除了base 10选项外,还有base 16和base 8选项:

选择包括

unsigned long long num = 285212672;
printf("Base 10: %llu\n", num);
num += 0xFFF; // For more interesting hex/octal output.
printf("Base 16: %llX\n", num); // Use uppercase A-F
printf("Base 16: %llx\n", num); // Use lowercase a-f
printf("Base  8: %llo\n", num);
puts("or 0x,0X prefix");
printf("Base 16: %#llX %#llX\n", num, 0ull); // When non-zero, print leading 0X
printf("Base 16: %#llx %#llx\n", num, 0ull); // When non-zero, print leading 0x
printf("Base 16: 0x%llX\n", num); // My hex fave: lower case prefix, with A-F

输出

Base 10: 285212672
Base 16: 11000FFF
Base 16: 11000fff
Base  8: 2100007777
or 0x,0X prefix
Base 16: 0X11000FFF 0
Base 16: 0x11000fff 0
Base 16: 0x11000FFF

【讨论】:

+l: "%llu" 让我吃惊。我使用“%ull”并收到警告说我提供了int @Rainning "%ull" 打印一个unsigned,然后是"ll"【参考方案11】:

非标准的东西总是很奇怪:)

对于长长的部分 在 GNU 下它是 Lllq

在 windows 下我相信它只是 ll

【讨论】:

【参考方案12】:

嗯,一种方法是使用 VS2008 将其编译为 x64

这会像你期望的那样运行:

int normalInt = 5; 
unsigned long long int num=285212672;
printf(
    "My number is %d bytes wide and its value is %ul. 
    A normal number is %d \n", 
    sizeof(num), 
    num, 
    normalInt);

对于 32 位代码,我们需要使用正确的 __int64 格式说明符 %I64u。于是就变成了。

int normalInt = 5; 
unsigned __int64 num=285212672;
printf(
    "My number is %d bytes wide and its value is %I64u. 
    A normal number is %d", 
    sizeof(num),
    num, normalInt);

此代码适用于 32 位和 64 位 VS 编译器。

【讨论】:

尝试一个实际的 64 位数字而不是 '285212672',我不相信第一个示例运行正确,编译到任何目标。【参考方案13】:

十六进制:

printf("64bit: %llp", 0xffffffffffffffff);

输出:

64bit: FFFFFFFFFFFFFFFF

【讨论】:

非常好!我想知道如何以十六进制表示形式获得它 但是,几乎所有的 C++ 和 C 编译器都会给出警告:警告:使用带有 'p' 类型字符的 'll' 长度修饰符 [-Wformat=]跨度> 这个完全错误的答案具有双重未定义行为,甚至没有开始回答问题 @AnttiHaapala 你说这个答案完全被双重未定义的行为所破坏,你能详细说明还是我应该删除它?还是把它当作一个好的坏例子? UB1:所有指针大小相同,sizeof(char *) == sizeof(long long *),因此 %p 上的大小修饰符毫无意义。 UB2:0xff.fff 是 int 类型,格式 %p 需要一个指针

以上是关于如何使用 printf 格式化 unsigned long long int?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 C 中打印“unsigned long”?

如何在C中使用signed / unsigned创建负二进制数?

Windows上未签名的__int64的printf格式

在 c 中的 unsigned short int 中分配零

如何在 C++ 中将 unsigned char[] 打印为 HEX?

unsigned short A = 10; printf("~A = %u ", ~A); char c=128; printf("c=%d ",c); (示