ChatGPT解决这个技术问题 Extra ChatGPT

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

#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 ),输出是正确的。您是否将任何选项传递给编译器?
请注意,三星 bada 的 newlib 似乎不支持“%lld”:developer.bada.com/forum/…
我建议使用 stdint.h 并明确说明变量中的位数。我们仍处于 32 位和 64 位体系结构之间的过渡时期,“unsigned long long int”在两者上并不意味着同样的事情。

r
rogerdpack

将 ll (el-el) long-long 修饰符与 u(无符号)转换一起使用。 (适用于 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 并为其中一个使用错误格式,例如使用 %d 而不是 %lld,那么即使是打印的参数不正确的参数之后也可能完全关闭(甚至可能导致 printf 崩溃)。本质上,变量参数是在没有任何类型信息的情况下传递给 printf 的,因此如果格式字符串不正确,则结果是不可预测的。
听到 Herb Sutter 在一次采访中说微软的客户不要求 C99,所以他们的纯 C 编译器已经冻结在 C90。这适用于编译为 C 的情况。如果编译为 C++,正如上面其他人所指出的,你应该没问题。
S
SSpoke

%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


N
Nathan Fellman

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

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 类型(实际上可能比指定的更宽)是强制性的。
佚名

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

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

t
tofutim

那是因为 %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 播种。最好避免。
S
ST3

在 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)使用仅支持 C89 规范的旧 Microsoft C 运行时。我只能访问真正古老且相当新的 Windows API 文档。所以很难准确地说出 I64u 支持是什么时候加入的。但这听起来像是 XP 时代。
S
Sandy

使用 VS2005 将其编译为 x64:

%llu 运行良好。


C
Community

显然,自 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" 更好。
c
chux - Reinstate Monica

如何使用 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"
B
Bernd Elkemann

除了人们多年前写的:

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

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

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

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


s
sparkes

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

对于 GNU 下的 long long 部分,它是 Lllq

在 Windows 下我相信它只是 ll


v
vzczc

好吧,一种方法是使用 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',我不相信第一个示例运行正确,编译到任何目标。
k
kungfooman

十六进制:

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

输出:

64bit: FFFFFFFFFFFFFFFF

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