uint16_t与printf的值差异

时间:2018-07-12 10:02:36

标签: c gcc printf scanf

以下程序的输出令人困惑。

uint16_t        first = 10, second = 20, third = 30;
// printf("%p\n", &first);
scanf("%d", &second);       // "%d" used intentionally.
printf("%" SCNu16 " ", first);
printf("%" SCNu16 " ", second);
printf("%" SCNu16 "\n", third);

在第一个printf发表评论后,我得到了10 20 0。 ("%d"中的scanf可能是造成此问题的原因。如果我使用"%" SCNu16代替%d,则可以正常工作。)

在没有注释的第一个printf中,我得到0 20 30。 困惑是-为什么printf导致输出差异?这是一致的行为。

2 个答案:

答案 0 :(得分:1)

在您的代码中,

 scanf("%d", &second); 

是未定义的行为。 %d期望参数是一个指向有符号整数类型(int)的指针。

引用C11,第§7.21.6.2章, fscanf函数

  

[...]除非用*指示禁止分配,否则   转换的结果放置在后面第一个参数指向的对象中   尚未收到转换结果的format参数。如果这个对象   没有适当的类型,或者无法表示转换结果   在对象中,行为是不确定的。

也就是说,SCNu N 宏适用于fscanf家族,fprintf()家族的对等物是PRIu N

答案 1 :(得分:0)

这是否是“一致行为”取决于您对其的定义。运行代码时,我会得到相同的行为,但是它并没有改变您的程序中存在未定义行为的事实。

我尝试使用-O3对其进行编译,然后在给出输入10 20 30时(无论是否带有上述20语句)都得到了输出printf

因此,尽管推测代码为什么会表现出有趣的方式可能很有趣,但这并不是很有意义。该代码无效,因此您无法保证。

我还尝试了切换变量声明的顺序:uint16_t third=30, second=20, first=10;行为已更改,但如果代码有效则不会更改。