在 3 个相同的 sscanf 调用中,中间一个不起作用

Out of 3 identical sscanf calls, the middle one does not work

我不知道发生了什么

在我的 C++ 程序中,我只想从命令行读取一些参数。

  1. 变量在 main() 的开头定义:
    uint32_t sampling_frequency;
    uint32_t samples_per_pixel;
    uint32_t total_samples;
    uint16_t amplification;
  1. 在对 argc 进行了一些验证之后,我正在阅读它们:
    sscanf(argv[3], "%" PRIu32, &sampling_frequency); 
    sscanf(argv[4], "%" PRIu32, &samples_per_pixel);
    sscanf(argv[5], "%" PRIu16, &amplification);
  1. 紧接着,打印获取的值以进行调试:
    printf("%s: %" PRIu32 "\n", argv[3], sampling_frequency);
    printf("%s: %" PRIu32 "\n", argv[4], samples_per_pixel);
    printf("%s: %" PRIu16 "\n", argv[5], amplification);
  1. 大惊喜来了,当我运行程序:
4.b:~/pro/spectr> ./spectr spectr_02.png out.wav 44100 10 2 -9 -8 -5 -4 -2 0 2 3 5
44100: 44100
10: 0
2: 2

如您所见,3 个 sscanf() 是相同的,但由于某些无法解释的原因,它仅对 argv[4] 无法正常工作。 问题出在 sscanf() 而不是 printf() ,因为代码稍后会检查数值并且它确实表现得好像是 0。 我不知道为什么会这样。

我在 Debian10 amd64 上用 g++ 编译。

PRI*宏仅适用于打印,不适用于扫描。

如果您想将这些宏与 sscanf() 一起使用,您需要使用 SCN* 版本。

像这样:

sscanf(argv[3], "%" SCNu32, &sampling_frequency); 
sscanf(argv[4], "%" SCNu32, &samples_per_pixel);
sscanf(argv[5], "%" SCNu16, &amplification);

您为 scanf 使用了错误的格式说明符宏。 “PRI”宏用于 printf 系列。 “SCN”宏用于 scanf 系列。

由于整数提升适用于可变参数,printf 只需要为大于 int 的类型指定大小说明符。对于小于 int 的类型和大于 int 的类型,scanf 都需要它们。

您的平台有一个 32 位 int 和一个 16 位 short。所以宏可能类似于 .

#define PRIu16 "u"
#define PRIu32 "u"
#define SCNu16 "hu"
#define SCNu32 "u"

所以你不正确地使用 scanf 的 PRIu16 宏会导致你将 4 个字节读入一个 2 字节的变量。由于您的系统是小端,并且可以使用未对齐的访问,因此可以将值正确读入 uint16_t 但也会覆盖接下来的两个字节的内存。该内存中的确切内容取决于编译器如何在堆栈上分配变量,