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

2024-02-26

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

b = a + ++a;

GCC 应注意并应报告为“未定义行为”代码(因为 ISO C 未指定求值操作数的加法顺序)。

然而,我尝试了语法并尝试了这个:

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

当然,我收到了警告

警告:“*a”上的操作可能未定义 [-Wsequence-point]

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

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

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

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


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

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

为了让 gcc 代码分析发现这个错误,编译器必须跟踪*a在其整个生命周期中。尽管在您的示例中看起来很简单,但是一个更复杂的程序,例如,数据被读入a来自用户输入的数据使得此类分析变得不可能。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

为什么 GCC 在此示例中不发出警告 的相关文章

随机推荐