如何使用 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 int
或long
%lu
--> 代表unsigned long int
或long unsigned int
或unsigned long
%lld
--> 代表long long int
或long long
%llu
--> 代表unsigned long long int
或unsigned long long
【讨论】:
【参考方案3】:您可能想尝试使用 inttypes.h 库,它为您提供类型,例如
int32_t
、int64_t
、uint64_t
等。
然后您可以使用它的宏,例如:
uint64_t x;
uint32_t y;
printf("x: %"PRId64", y: %"PRId32"\n", x, y);
这是“保证”不会给您带来与long
、unsigned long long
等相同的麻烦,因为您不必猜测每种数据类型中有多少位。
【讨论】:
这些PRId64
、PRId32
宏定义在哪里?
@happy_marmoset:它们在inttypes.h
中定义
我认为您需要 PRIu64
和 PRIu32
来获取无符号整数。
inttypes.h
是标准的吗?不会是stdint.h
吗?
请注意,这些精确宽度类型是可选的,因为有些架构没有这些精确宽度的整数类型。只有leastX
和fastX
类型(实际上可能比指定的更宽)是强制性的。【参考方案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
。这个答案有"%" PRIu64
和unsigned 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 下它是 L
、ll
或 q
在 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中使用signed / unsigned创建负二进制数?
在 c 中的 unsigned short int 中分配零
如何在 C++ 中将 unsigned char[] 打印为 HEX?
unsigned short A = 10; printf("~A = %u ", ~A); char c=128; printf("c=%d ",c); (示