为什么 sscanf %lx 在 64 位环境中读取任何第一个 uint32_t 的“0”?

Why does sscanf %lx read "0" for any first uint32_t on a 64-bit environment?

我有以下 C 代码:

uint32_t a = 1, b = 2;
sscanf("0xbadf00d 0xdeadbeef", "%lx %lx", &a, &b);
printf("%lx %lx", a, b);

在使用 gcc 的 64 位 Linux 机器上,如果我使用标志 -m32 进行编译,我会得到正确的输出:badf00d deadbeef,但默认情况下我会得到奇怪的输出0 deadbeef

第二种情况是怎么回事?我是不是使用了错误的转换说明符字符,或者,有没有办法在没有此编译器标志的情况下解决问题?

您正在使用 l 长度修饰符,它适用于 unsigned long,但 uint32_t 在 64 位上 不是 unsigned long系统,唯一的例外是 Windows。没有定义 uint32_t 的标准长度修饰符,但是 header 中有包含长度修饰符(通常是空字符串)的宏。

可移植的解决方案是使用 <inttypes.h>:

中定义的宏
#include <stdint.h>
#include <stdio.h>
#include <inttypes.h>

int main() {
    uint32_t a = 1, b = 2;
    sscanf("0xbadf00d 0xdeadbeef", "%" SCNx32 " %" SCNx32, &a, &b);
    printf("%" PRIx32 " %" PRIx32, a, b);
}

在您实际使用的几乎所有系统上,在宏扩展后,这与以下内容相同:

#include <stdint.h>
#include <stdio.h>

int main() {
    uint32_t a = 1, b = 2;
    sscanf("0xbadf00d 0xdeadbeef", "%x %x", &a, &b);
    printf("%x %x", a, b);
}