c - 为什么 GCC 不在此示例中发出警告

标签 c pointers gcc compiler-warnings compiler-optimization

启用 -Wsequence-point 后,当发现未定义的行为代码时,GCC 应该警告用户。例如

b = a + ++a;

应该被 GCC 注意到并且应该被报告为“未定义行为”代码(因为 ISO C 没有指定计算加法操作数的顺序)。

但是,我尝试了语法并尝试了这个语法:

int *a = malloc(sizeof(int) * 2);
a[0] = 1;
printf("%d\n", *(a + (*a)++ - *a));

当然,我得到了警告

warning: operation on '*a' may be undefined [-Wsequence-point]

这是我所期望的,因为 *a 的值(即 a[0])在处理第三个操作数时可能会递增,也可能不会递增。但是,我尝试了以下方法:

int *a = malloc(sizeof(int) * 2);
a[0] = 1;
printf("%d\n", *(a + (*a)++ - 1));

我很惊讶,因为我没有收到任何警告。这不应该也是UB吗?我的意思是,根据 ISO C99,可以在表达式评估期间的任何时候评估后增量操作(逗号运算符和三元运算符除外)。在我的后一个示例中,我没有递增指针,而是递增它指向的整数。因此,根据标准,它可以在任何时候递增(这意味着它可以在整个表达式求值后递增),因此程序可以同时打印 12,对吧?

为什么 GCC 不发出任何警告?还是我错过了什么?我是否错误地理解了规范?

最佳答案

gcc的静态分析工具无法处理这种情况。

表达式 *(a + (*a)++ - x) 对于 gcc 的静态分析来说太难了,因为在某些非常特定的情况下,由于缺少序列点,它会导致未定义的行为情况 - 即,当 *a 包含 x 时。这是 (*a)++ - x 相互“撤消”的时候,因此整体表达式等同于 *a 加上一些副作用。

为了让 gcc 代码分析发现这个错误,编译器必须在其整个生命周期中跟踪 *a 的内容。尽管在您的示例中它看起来很简单,但是一个更复杂的程序,例如,从用户输入中将数据读入 a 中,无法进行此类分析。

关于c - 为什么 GCC 不在此示例中发出警告,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43963156/

相关文章:

具有 C 扩展的 Python 项目 - 结构、导入和测试

c - 返回字符串数组并将其分配给 C 中的变量

c++ - 在构造函数 C++ 中将指针传递给 self

python - mingw32-gcc 编译 Cython 输出 : unknown multiarch location for pyconfig. h (和其他警告)

c++ - 有没有办法强制 C++ 编译器不优化静态库中的特定静态对象?

c++ - 参数包函数参数可以默认吗?

c++ - reinterpret_cast 是否保证不更改源指针的地址?

c - 在C中初始化链表中的变量

c - 结构体中元素之一的数组初始化

android - 添加 ndk 对 c(不是 cpp)的支持