我正在使用32位系统。当我尝试在单个printf中打印多个64位值时,它无法再打印(即第2,第3 ......)个变量值。
示例:
uint64_t a = 0x12345678;
uint64_t b = 0x87654321;
uint64_t c = 0x11111111;
printf("a is %llx & b is %llx & c is %llx",a,b,c);
为什么这个printf不能打印所有值?
我正在修改我的问题
printf("a is %x & b is %llx & c is %llx",a,b,c);
通过这样做的结果是:a是12345678& b是8765432100000000& c是1111111100000000
如果我没有正确打印出一个值,那么为什么其他的价值会发生变化?
答案 0 :(得分:14)
您应该使用<inttypes.h>
printf("a is %"PRIx64" & b is %"PRIx64" & c is %"PRIx64"\n",a,b,c);
它很难看,但是它很便携。这是在C99中引入的,因此您需要符合C99的编译器。
答案 1 :(得分:10)
您需要使用正确的格式:
#include <stdio.h>
#include <stdlib.h>
#include <inttypes.h>
int main(void)
{
uint64_t a = 0x12345678;
uint64_t b = 0x87654321;
uint64_t c = 0x11111111;
printf("a is %#" PRIx64
" & b is %#" PRIx64
" & c is %#" PRIx64 "\n",
a, b, c);
return EXIT_SUCCESS;
}
输出:
a is 0x12345678 & b is 0x87654321 & c is 0x11111111
答案 2 :(得分:2)
它会在我的计算机上打印所有内容,但由于%llx
期望long long unsigned int
,因此有三个编译时警告。
您确定需要使用64位类型吗?所有三个十六进制代码只有32位。也许你可以只使用32位并执行:
unsigned int a = 0x12345678;
unsigned int b = 0x87654321;
unsigned int c = 0x11111111;
printf("a is %x & b is %x & c is %x",a,b,c);
(或者使用相当于32位unsigned int的stdint)
除非你需要它们是64位,否则你可以在以后添加更多位。
答案 3 :(得分:1)
使用:
"%lli" for int64_t
"%llu" for uint64_t
"%llx" for hex
"%llX" for HEX
查看“inttypes.h”。
答案 4 :(得分:1)
适用于名为 Stack Overflow 的论坛,导致意外printf()
输出的原因是堆栈错位。 %x
转换规范与函数参数a
之间的大小不匹配会导致错位。
编译语句时
printf("a is %x & b is %llx & c is %llx",a,b,c);
编译器生成机器代码,以从右到左的顺序推送堆栈上的函数参数。
编译器使用变量声明而不是格式字符串来确定堆栈上每个参数的数据大小(可能除了生成警告之外)。在x86 CPU中(与大多数机器一样),堆栈指针随着每次推送而递减。当输入printf()
库函数时,堆栈因此具有以下布局:
00A4: ... 00A0: 00000000 009C: 11111111 Variable 'c' pushed on the stack as uint64 0098: 00000000 0094: 87654321 'b' pushed on the stack as uint64 0090: 00000000 008C: 12345678 'a' pushed on the stack as uint64 0088: <pointer to format string> 0084: <return address>
对于此示例,堆栈顶部地址0084是任意的。
由于所有三个变量都声明为uint64_t
,因此编译后的代码将这些变量作为64位值推送到堆栈上。对于像x86 CPU这样的小端机器,每个uint64
值的高字节最终会出现在更高的地址中。
printf()
的实现使用格式字符串来确定堆栈上参数的数量和大小。与编译器不同,printf()
不接收有关原始变量声明的信息。第一个转换规范是%x
,因此printf()
期望a
为32位值,因此,printf()
按如下方式解析堆栈布局:
00A4: ... 00A0: 00000000 009C: 11111111 0098: 00000000 '%llx' reads 'c' as uint64, but from the wrong address 0094: 87654321 0090: 00000000 '%llx' reads 'b' as uint64, but from the wrong address 008C: 12345678 '%x' causes printf() to read 'a' as a uint32 0088: <pointer to format string> 0084: <return address>
堆栈错位解释了为什么a
按预期打印12345678,但b
和c
已被有效地左移32位到8765432100000000和1111111100000000。
将第一个%x
转换规范或转换参数a
更正为uint32可以解决问题。