以下程序的输出令人困惑。
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
导致输出差异?这是一致的行为。
答案 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;
行为已更改,但如果代码有效则不会更改。