c - C 未经检查的函数返回未定义的行为
问题描述
在 c 中,这种模式相当普遍:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int init_ptr_or_return_err(int *p) {
srand(time(NULL));
// random to make code compile/demonstrate the question
int error = rand() % 2;
if (error) {
return 1;
}
*p = 10;
return 0;
}
int main() {
int a;
init_ptr_or_return_err(&a);
printf("a = %d\n", a);
return 0;
}
在上面的 main 函数中,如果不检查函数的返回码,访问 a 的值可能在运行时是未定义的(但这不是静态确定的)。因此,它通常包装在一个块中,例如:
if (init_ptr_or_return_err(&a)) {
// error handling
} else {
// access a
}
在这种情况下,编译器知道 a 在 else 中被初始化,因为当且仅当它设置 a 时,该函数才返回 0。因此,从技术上讲,在 else 中访问 a 是已定义的,但在 if 中访问 a 是未定义的。但是,return 0
可以很容易地“从文件中返回一些固定但静态未知的值”(然后在访问 a 之前只检查该值)。因此,无论哪种情况,都无法静态确定 a 是否已初始化。
因此,在我看来,一般来说,编译器不能静态地决定这是否是未定义的行为,因此不应该例如优化它。
此类代码的确切语义是什么(它是未定义的行为,还是其他东西,或者静态和运行时未定义的行为之间是否存在差异)以及标准在哪里指定了这一点?如果这不是标准定义的,我使用的是 gcc,所以在 gcc 上下文中的答案会很有帮助。
解决方案
绝大多数未定义的行为不是静态确定的。大多数未定义行为的形式是“如果达到此语句,并且满足这些条件,则程序具有未定义行为”。
这里就是这种情况。当一次调用程序rand()
返回奇数时,它具有未定义的行为。rand()
当它在返回偶数的时候被调用时,行为是明确定义的。
此外,编译器可以自由假设您只会在rand()
返回偶数时调用程序。例如,它可能会优化分支到return 1;
案例,因此总是打印 10。
推荐阅读
- excel - 根据列值将启用宏的文件拆分为单独的文件
- ios - 为什么我的其他 iOS 设备上没有收到 Firebase Cloud 消息通知?
- tensorflow - Keras 找不到指定的模块
- javascript - 尝试使用 MVC 将 DropDownList 值发送到模态中的 ajax 函数时出现空值 - 实体
- angular - 将标头令牌获取为未定义
- python - AttributeError:“列表”对象在我的 python 堆排序中没有属性“A”
- javascript - SCSS根据id添加动画
- php - 如何获得循环结果?
- javascript - 如何使用 Vue 指令添加自定义 html 和样式?可能吗?
- composer-php - 作曲家包问题