在 3 个相同的 sscanf 调用中,中间一个不起作用
Out of 3 identical sscanf calls, the middle one does not work
我不知道发生了什么
在我的 C++ 程序中,我只想从命令行读取一些参数。
- 变量在 main() 的开头定义:
uint32_t sampling_frequency;
uint32_t samples_per_pixel;
uint32_t total_samples;
uint16_t amplification;
- 在对 argc 进行了一些验证之后,我正在阅读它们:
sscanf(argv[3], "%" PRIu32, &sampling_frequency);
sscanf(argv[4], "%" PRIu32, &samples_per_pixel);
sscanf(argv[5], "%" PRIu16, &lification);
- 紧接着,打印获取的值以进行调试:
printf("%s: %" PRIu32 "\n", argv[3], sampling_frequency);
printf("%s: %" PRIu32 "\n", argv[4], samples_per_pixel);
printf("%s: %" PRIu16 "\n", argv[5], amplification);
- 大惊喜来了,当我运行程序:
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, &lification);
您为 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 但也会覆盖接下来的两个字节的内存。该内存中的确切内容取决于编译器如何在堆栈上分配变量,
我不知道发生了什么
在我的 C++ 程序中,我只想从命令行读取一些参数。
- 变量在 main() 的开头定义:
uint32_t sampling_frequency;
uint32_t samples_per_pixel;
uint32_t total_samples;
uint16_t amplification;
- 在对 argc 进行了一些验证之后,我正在阅读它们:
sscanf(argv[3], "%" PRIu32, &sampling_frequency);
sscanf(argv[4], "%" PRIu32, &samples_per_pixel);
sscanf(argv[5], "%" PRIu16, &lification);
- 紧接着,打印获取的值以进行调试:
printf("%s: %" PRIu32 "\n", argv[3], sampling_frequency);
printf("%s: %" PRIu32 "\n", argv[4], samples_per_pixel);
printf("%s: %" PRIu16 "\n", argv[5], amplification);
- 大惊喜来了,当我运行程序:
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, &lification);
您为 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 但也会覆盖接下来的两个字节的内存。该内存中的确切内容取决于编译器如何在堆栈上分配变量,