C语言printf嵌套scanf的参数求值顺序与输出差异探究
两段C语言printf代码输出差异原因分析及参数求值机制确认
测试代码
code1
#include <stdio.h> int main() { int z = 9; printf("%d\n", printf("%d%d", scanf("%d", &z), z)); return 0; }
code2
#include <stdio.h> int main() { int z = 9; printf("%d\n", printf("%d%d", z, scanf("%d", &z))); return 0; }
测试结果
| 输入 | code1输出 | code2输出 |
|---|---|---|
| 1 | 192 | 112 |
| a | 092 | 902 |
输出差异原因及求值机制说明
先明确两个核心前提:
scanf的返回值:成功读取输入项的数量,输入合法整数时返回1,输入非整数(如a)时返回0,且此时目标变量z的初始值不会被修改。- C语言标准未指定函数参数的求值顺序,你观察到的从右向左求值是当前所用编译器(如GCC)的具体实现逻辑,不同编译器可能采用左向右或其他顺序,但你的测试结果完全符合右向左求值的行为。
输入为1时的逻辑拆解
code1:
内层printf的两个参数按右向左求值:- 先计算右侧的
z:此时z是初始值9,得到数值9。 - 再计算左侧的
scanf:读取输入1,将z修改为1,返回值1。
内层printf输出1+9即19,而printf的返回值是输出的字符数(此处为2),外层printf输出这个2,最终得到192。
- 先计算右侧的
code2:
内层printf的两个参数按右向左求值:- 先计算右侧的
scanf:读取输入1,将z修改为1,返回值1。 - 再计算左侧的
z:此时z已被修改为1,得到数值1。
内层printf输出1+1即11,外层printf输出返回值2,最终得到112。
- 先计算右侧的
输入为a时的逻辑拆解
code1:
内层printf的两个参数按右向左求值:- 先计算右侧的
z:取初始值9,得到数值9。 - 再计算左侧的
scanf:读取a失败,返回0,z保持初始值9不变。
内层printf输出0+9即09,外层printf输出返回值2,最终得到092。
- 先计算右侧的
code2:
内层printf的两个参数按右向左求值:- 先计算右侧的
scanf:读取a失败,返回0,z保持初始值9不变。 - 再计算左侧的
z:取当前值9,得到数值9。
内层printf输出9+0即90,外层printf输出返回值2,最终得到902。
- 先计算右侧的
关于参数求值顺序的确认
C语言标准(C99及后续版本)明确将函数参数的求值顺序列为未指定行为——编译器可自由选择求值顺序,从右向左只是GCC等主流编译器的常用实现方式。代码不能依赖这种顺序,否则在其他编译器上可能产生完全不同的结果,属于需要避免的非可移植写法。
内容的提问来源于stack exchange,提问作者anon
相关产品推荐
相关产品推荐

