【问题标题】:Can bitwise operators have undefined behavior?位运算符可以有未定义的行为吗?
【发布时间】:2018-09-26 09:54:46
【问题描述】:

按位运算符(~&|^)对其提升的操作数的按位表示进行运算。这样的操作会导致未定义的行为吗?

例如,~ 运算符在 C 标准中是这样定义的:

6.5.3.3 一元算术运算符

~ 运算符的结果是其(提升的)操作数的按位补码(即,当且仅当未设置转换后的操作数中的相应位时,结果中的每个位都被设置)。整数提升在操作数上执行,结果具有提升的类型。如果提升的类型是无符号类型,则表达式~E 等于该类型中可表示的最大值减去E

在所有架构上,~0 生成一个位模式,其中符号位设置为 1,所有值位设置为 1。在一个补码架构上,这种表示对应于一个负零。这个位模式可以是陷阱表示吗?

对于更常见的架构,是否还有其他涉及简单位运算符的未定义行为示例?

【问题讨论】:

  • 不,在一个补码体系结构上,~0 生成一个位模式,其中 all 位设置为 1。为什么你认为非符号位会保持为零?这不是按位补码。
  • 1999 C 标准,第 6.5 节第 4 段。“一些运算符(一元运算符 ~ 和二元运算符 <<>>&^ 和 @ 987654341@,统称为按位运算符)必须具有整数类型的操作数。这些运算符返回的值取决于整数的内部表示,并且具有有符号类型的实现定义和未定义方面 。” (我的粗体强调)。
  • @chqrlie 好的,尽管该线程可以使用标准引号。也许也相关this thread - 因为标准中的脚注,算术运算不能产生陷阱表示。 (大概意思是“除了已经定义的负零情况”)
  • 去掉了双重标签——问题中的标准引号和答案全部地址C; C++ 是一种不同的语言,不同语言的问题不应该被双重标记,除非它们是关于互操作性等的。

标签: c language-lawyer bitwise-operators ones-complement


【解决方案1】:

对于一个人的补码系统,在有符号整数中明确列出了那些不支持负零的陷阱值的可能性(C11 6.2.6.2p4):

如果实现不支持负零,则 &、|、^、~、> 运算符的行为以及会产生此类值的操作数是未定义的。

再说一次,一个人的补语系统并不常见。比如GCC不支持!

C11 确实暗示 实现定义和未定义的方面只允许 signed types (C11 6.5p4)。

【讨论】:

  • 2's complement 中,值为-8 ,但负零是一个重要概念,例如,定义-INFINITY。它在2's complement 中是如何工作的,因为大多数实现都只使用这种表示法。
  • @0decimal0 我不明白你在这里问的是什么
  • @0decimal0 整数没有无穷大
  • @Antti Haapala 我认为我们应该完全忘记补码,因为现在使用的编译器不支持它们。今天使用的唯一机器是一些在兼容模式下工作的 univac 服务器。但是在这种模式下没有可用的 C 编译器,而且(至少据我所知)也没有交叉编译器。
猜你喜欢
  • 1970-01-01
  • 2021-06-11
  • 1970-01-01
  • 2016-12-21
  • 1970-01-01
  • 1970-01-01
  • 2019-06-10
  • 2020-10-10
相关资源
最近更新 更多