定义的行为警告?

当它发现一个含有未定义/未指定/实现定义行为的语句时,编译器是否会发出警告(如果它引发错误,则更好)?

可能将一个声明标记为错误,标准应该这样说,但它至少可以警告编码人员。 实施这样的选择有没有技术上的困难? 还是仅仅是不可能的?

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


这一切归结为

  • 实施质量:警告越准确和有用,越好。 总是打印的编译器:“这个程序可能或可能不会调用未定义的行为”,然后编译它,是非常没用的,但是符合标准。 谢天谢地,没有人写这些编译器:-)。

  • 易于确定:编译器可能不容易确定未定义的行为,未指定的行为或实现定义的行为。 假设您有一个5层深的调用堆栈,其中const char *参数从顶层传递到链中的最后一个函数,最后一个函数使用该const char *作为第一个函数调用printf()论据。 你想让编译器检查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("%dn", i);
        return 0;
    }
    

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

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


    海湾合作委员会警告在这种情况下(至少与 - -Wall ):

    #include <stdio.h>
    
    int main(int argc, char *argv[])
    {
      int a[5];
      int i = 0;
    
      a[i] = ++i;
    
      printf("%dn", a[0]);
    
      return 0;
    }
    

    得到:

    $ make
    gcc -Wall main.c -o app
    main.c: In function ‘main’:
    main.c:8: warning: operation on ‘i’ may be undefined
    

    编辑:

    手册页的快速阅读表明, -Wsequence-point会做,如果你不想-Wall出于某种原因。


    相反,使任何类型的诊断未定义行为不需要编译器:

    §1.4.1:
    这套可诊断规则由本国际标准中的所有句法和语义规则组成,除了那些包含“不需要诊断” 或被描述为导致“未定义行为”的明确标记的规则

    强调我的。 虽然我同意这可能是好的,但编译器有足够的问题试图符合标准,更不用说教程序员如何编程。

    链接地址: http://www.djcxy.com/p/73165.html

    上一篇: defined behaviour warnings?

    下一篇: Copy constructor called everytime a default constructor is called?