Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/55.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 有没有一个规则来识别UB?_C_Undefined Behavior - Fatal编程技术网

C 有没有一个规则来识别UB?

C 有没有一个规则来识别UB?,c,undefined-behavior,C,Undefined Behavior,我读了一个非常广泛的问题,遇到了一些我以前不知道的UB 我不时看到UB的主要原因是在两个序列点之间更改变量两次。例如:x=x++或z=y+++++y。通过阅读在两个序列点之间两次更改变量有助于我了解这些情况的根本原因 但是像负片移位这样的事情呢?(intx=8(从评论中编译答案,包括我的评论。) 查找实际未定义行为(UB)的良好起点是以下参考: 是的,有很多案例,对它们进行分组是很困难的。C11标准的附录J.2在第557-571页记录了未定义的行为(每个结尾页上只有几行,所以比14页多一点) 参

我读了一个非常广泛的问题,遇到了一些我以前不知道的UB

我不时看到UB的主要原因是在两个序列点之间更改变量两次。例如:
x=x++
z=y+++++y。通过阅读在两个序列点之间两次更改变量有助于我了解这些情况的根本原因

但是像负片移位这样的事情呢?(
intx=8(从评论中编译答案,包括我的评论。)

查找实际未定义行为(UB)的良好起点是以下参考:

是的,有很多案例,对它们进行分组是很困难的。C11标准的附录J.2在第557-571页记录了未定义的行为(每个结尾页上只有几行,所以比14页多一点)

参考一篇相关文章,该文章讨论了UB的类型、定位工具,并包含UB列表;长且(作者有意)完整(davmac的cortesy):

实现“可记忆”的两种方法:

  • ,重点关注不可避免的平台依赖性:

    我的一般经验法则是——任何看起来会随着不同的实现(目标、平台等)而改变行为的东西都是“发现”UB的危险信号

  • ,重点关注平衡标准化和优化的问题:

    如果很难让硬件供应商同意这一点,或者很难明确定义并为优化实施留出空间,那么很可能是UB

  • 不幸的是,所有这些“规则”都不容易应用。 检查实际标准不方便。 这两条经验法则是基于相当多的经验;您要么需要设计一些编译器和/或处理器,要么因为它们之间的差异而受到很大的影响

    因此,“是否有一种简单的方法可以识别UB?”的实际答案是 很可能是简单的“否。

    具体来说,带负数的位移位是否被视为整数溢出?如果是,为什么

    事实并非如此,因为按任何数量移动0都不会溢出,但将0的值移动负值仍然是未定义的行为。(我假设如果第一次将移位量重新解释为无符号整数,那么它可以是整数溢出,此时它将是大的并且肯定超出允许的范围,如果被解释为乘数幂-2,则如果移位值为非零,则实际移位会肯定溢出)。 简言之,负的位移位会产生未定义的行为,因为语言标准说它会

    如果不是,这是更大现象的一部分吗

    John Regehr在中给出了一些广泛的UB类别。无效金额的转移属于“其他UB”类别

    是否存在(其他)无法归入一个潜在原因的独特案例

    是的,请参阅上面的文章。其中(这些是直接从博客文章中摘取的):

    • 不指向或刚好超出同一数组对象的指针将被减去(6.5.6)
    • 对象的存储值不是由允许类型的左值访问的(6.5)
    • 非空源文件不以不紧跟反斜杠字符的新行字符结尾,也不以部分预处理标记或注释结尾(5.1.1.2)
    您可能会以某种方式对这些示例和其他示例进行分类,但这取决于您希望如何进行分类


    特别是,上面的最后一个示例(关于源文件不以新行结尾)显示了某些规则的任意性。

    x的情况下,负移位未定义,长移位也未定义(对于N位整数类型为N位或更多位移位).标准是这么说的。你必须知道它是这么说的。是的,有很多案例,对它们进行分组是很困难的。C11标准的附录J.2在第557-571页记录了未定义的行为(每个结尾页上只有几行,所以比14页多一点).定期阅读以了解未定义的内容。不,我也没有记住。@JonathanLeffler这是一个令人印象深刻的列表,thx!尽管我希望有更容易记住的:)回答你的问题——我希望有一些更容易记住的东西——我的一般经验法则是——任何看起来会随着不同的实现(目标、平台等)而改变行为的东西都是“发现”的危险信号UB。然后我用列表确认。这是有意义的,因为标准是在抽象机器上定义的,而不是在任何实现上。因此,涉及实现的方面必须保持未定义。小心实现定义的行为。@Jean BaptisteYunès您非常有说服力的示例的更抽象的版本是“如果很难让硬件供应商在这一点上达成一致,或者很难明确定义并为优化实施留出空间,那么很可能是UB”。这可能是“易于记忆的经验法则”"OP正在寻找。UB类型的优秀总结:我会把这个标记为一个社区答案,因为大部分都不是你的话。如果你这样做,请删除顶部的括号注释。现在你有了这个内容的答案,我愿意把你的好链接从我的答案中删除,以便不带走你的CRIDI。t、 你想让我这样做吗?还有一些平台,其中只有足够的
    y
    位连接到移位单元,以支持有意义的移位范围(即,好像
    y
    被屏蔽为
    x
    位大小)。@TobySpeight:通常是
    x
    
    unsigned temp = x;
    unsigned count=y;
    while(count--)
      temp<<=1;
    z=temp;