C语言中printf参数求值顺序未指定时,errno与strerror()的行为疑问
关于printf参数求值顺序与errno的未指定行为问题
你的问题切中了C语言里一个容易被忽略的未指定行为点,咱们一步步拆解清楚:
首先明确结论:这段代码的行为确实属于C标准定义的「未指定行为」,你无法保证输出的errno值一定是fopen失败时的原始错误码,原因如下:
函数参数的求值顺序未指定:C标准明确规定,函数调用中各个实参的求值顺序是未指定的——编译器完全可以自由选择先计算
errno,再调用strerror(errno),或者反过来先调用strerror,再读取errno的值。strerror可能修改errno:虽然
strerror的主要作用是返回对应错误码的描述字符串,但如果传入的errno值是无效的(比如某些自定义的错误码),部分实现的strerror会将errno设置为EINVAL。如果编译器选择先调用strerror(errno),那么当后续读取errno参数时,它的值已经被strerror修改,导致输出的错误码和fopen失败时的原始值不一致。两种可能的执行路径:
- 若编译器先读取
errno的值并保存到printf的参数列表中,再调用strerror:此时即使strerror修改了errno,输出的第一个errno仍然是fopen失败时的原始值,结果符合预期。 - 若编译器先调用
strerror(errno),再读取errno:此时如果strerror修改了errno,输出的errno就变成了strerror修改后的值,和原始错误码不符。
- 若编译器先读取
因为C标准没有强制要求参数的求值顺序,编译器可以任选一种方式实现,所以这段代码的行为是不可预测的——你不能依赖某一种执行顺序来保证输出正确。
内容的提问来源于stack exchange,提问作者babon
相关产品推荐
相关产品推荐

