未定义/未指定/实现定义的行为警告?

leg*_*s2k 5 c c++ undefined compiler-warnings unspecified

当它注意到具有未定义/未指定/实现定义的行为的语句时,编译器是否不能发出警告(如果它抛出错误会更好)?

可能会将语句标记为错误,标准应该这样说,但它至少可以警告编码器.实施这种方案有任何技术困难吗?或者它只是不可能?

我得到这个问题的原因是,在语句中,a[i] = ++i;如果不知道代码是在尝试引用变量并在到达序列点之前在同一语句中修改它.

Alo*_*hal 7

这一切归结为

  • 实施质量:警告越准确和有用,越好.一个总是打印的编译器:"这个程序可能会也可能不会为每个程序调用未定义的行为",然后编译它,这是非常没用的,但是符合标准.值得庆幸的是,没有人写这些编译器:-).

  • 易于确定:编译器可能无法轻松确定未定义的行为,未指定的行为或实现定义的行为.假设你有一个深度为5级的调用堆栈,一个const char *参数从顶层传递到链中的最后一个函数,最后一个函数调用printf()const char *作为第一个参数.您是否希望编译器检查const char *以确保它是正确的?(假设第一个函数对该值使用了一个文字字符串.)const char *从文件中读取文件的时间,但是您知道该文件将始终包含正在打印的值的有效格式说明符吗?

  • 成功率:编译器可能能够检测到许多可能未定义,未指定等的构造; 但是"成功率"非常低.在这种情况下,用户不希望看到大量"可能未定义"的消息 - 过多的虚假警告消息可能隐藏真实的警告消息,或者提示用户在"低警告"设置下编译.那很不好.

对于您的特定示例,请gcc发出有关"可能未定义"的警告.它甚至警告printf()格式不匹配.

但是,如果您希望编译器为所有未定义/未指定的情况发出诊断,则不清楚是否应该/可以工作.

假设您有以下内容:

#include <stdio.h>
void add_to(int *a, int *b)
{
    *a = ++*b;
}

int main(void)
{
    int i = 42;
    add_to(&i, &i); /* bad */
    printf("%d\n", i);
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

编译器是否应警告您*a = ++*b;线路?

正如gf在评论中所说,编译器无法跨翻译单元检查未定义的行为.经典示例将变量声明为一个文件中的指针,并将其定义为另一个文件中的数组,请参阅comp.lang.c FAQ 6.1.

  • 不要忘记*"只要涉及到编译源外部的调用,编译器就无法确定未定义的行为"* (5认同)