这对int64_t的处理是GCC和Clang的错误吗?
现在,你们中的一些人会想要大喊未定义的行为,但是有一个问题. int64_t类型不是由C标准定义,而是由POSIX定义.POSIX将此类型定义为:
它不会留下这个实现来定义,并且绝对不允许将它视为无界整数.
显然,这里有一个问题……它是什么? 最佳答案
你不需要去POSIX对它进行排序,ISO C控制这个特定的方面(下面的参考是C11标准).
这个答案的其余部分将成为所有“语言律师”,以显示为什么将未添加的行为添加到已签名的值中,以及为什么两个答案(真和假)都有效. 首先,您在ISO中未定义int64_t的争论并不十分正确.第7.20.1.1节精确宽度整数类型在引用intN_t类型时指出:
这就是为什么你不需要担心POSIX以某种方式定义这些类型的原因,因为ISO定义它们完全相同(两个补码,没有填充等),假设它具有适当的能力. 所以,既然我们已经建立了ISO确定它们(如果它们在实现中可用),现在让我们看看6.5 Expressions / 5:
添加两个相同的整数类型肯定会给你相同的类型(至少在int64_t的等级,远高于整数提升完成的点1),因为这是由6.3.1.8中规定的通常的算术转换决定的.在处理各种浮点类型(其中int64_t不是)的部分之后,我们看到:
在同一部分的早期,您会找到一个声明,该声明在找到常见类型后指示结果的类型:
因此,假设INT64_MAX 1的结果实际上不适合int64_t变量,则行为未定义. 根据你的注释,int64_t的编码表明添加一个将包装,你必须明白,它不会改变它根本未定义的子句.在这种情况下,实现仍然可以自由地执行任何操作,即使根据您的想法没有意义. 并且,在任何情况下,表达式INT64_MAX 1> INT64_MAX(其中1经历整数提升为int64_t)可以简单地编译为1,因为可以说比实际递增值和进行比较更快.这是正确的结果,因为任何东西都是正确的结果:-) 从这个意义上讲,它与实现转换没有什么不同:
进入更简单,几乎肯定更快:
您可能认为答案会更好,因为9或12(取决于何时执行副作用)但是,如果未定义的行为是打破编码器和编译器之间的契约,编译器可以自由地做任何想做的事情. 在任何情况下,如果你想要一个定义良好的函数版本,你可以选择以下内容:
这可以在不诉诸未定义的行为的情况下获得所需/预期的结果:-) 1如果int的宽度实际上大于64位,则此处可能存在边缘情况.在这种情况下,很可能整数提升将强制int64_t为int,允许表达式被很好地定义.我没有详细研究过,所以可能是错的(换句话说,不要把它视为我答案的福音部分)但是值得记住的是检查你是否得到了一个int的实现超过64位宽. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |