移位何时会导致未定义的行为

Fre*_*rik 2 c

我尝试找到一个列出所有可能性的好答案(也许只有一种?)。

那么考虑到有符号数和无符号数,C 语言中导致 UB 移位的方法有哪些?

小智 5

C99 标准对按位移位运算符有这样的规定(添加了强调,并且^用于表示求幂):

\n\n
\n

\xc2\xa76.5.7.3:对每个操作数执行整数提升。结果的类型是提升后的左操作数的类型。如果右操作数的值为负数或大于或等于提升的左操作数的宽度,则行为未定义。
\n \xc2\xa76.5.7.4 : 的结果E1 << E2E1左移位E2位置;空出的位用零填充。如果E1具有无符号类型,则结果的值为E1 \xc3\x97 2^E2,比结果类型中可表示的最大值再模一减少。如果E1具有有符号类型和非负值,并且E1 \xc3\x97 2^E2\n 可在结果类型中表示,则这就是结果值;否则,行为是未定义的。
\n **\xc2\xa76.5.7.5
:结果E1 >> E2E1右移位E2位置。如果\n E1具有无符号类型或E1具有有符号类型和非负值,则结果的值是 的商的整数部分E1 / 2^E2如果E1具有有符号类型和负值,则结果值是实现定义的。

\n
\n\n

因此,总而言之,如果满足以下任一条件,则行为是未定义的:

\n\n
    \n
  • 右操作数有符号且为负,或者
  • \n
  • 右操作数大于或等于左操作数的宽度(提升后),或者
  • \n
  • 左操作数有符号且为负,或者
  • \n
  • 执行左移并且左操作数是有符号的,并且结果值不能表示为有符号整数
  • \n
\n