为什么要担心'undefined behavior'>>签名类型?

Why worry about 'undefined behavior' in >> of signed type?

本文关键字:gt 类型 undefined 担心 为什么 behavior      更新时间:2023-10-16

我的问题与此有关,将包含几个问题。

对我来说,上述问题最明显的(意味着我会在我的代码中使用它)解决方案就是这个:

uint8_t x = some value;
x = (int8_t)x >> 7;
是的

,是的,我听到了你们的声音....未定义的行为,这就是我没有发布我的"解决方案"的原因。

有一种感觉(也许这只是我病态的头脑),术语"未定义的行为"在 SO 上被过度使用,只是为了证明如果问题被标记为 c/c++,则对某人投反对票是合理的。

所以 - 让我们(暂时)抛开C/C++标准,考虑日常生活/编程,真正的编译器实现以及它们为当代硬件生成的代码。

考虑到以下几点:

  • 据我所知,我遇到的所有硬件都有不同的算术和逻辑转换指令。
  • 我认识的所有编译器都>>转换为有符号类型的算术移位和无符号类型的逻辑移位。
  • 我不记得有任何编译器在 C/C++ 代码中使用>>时发出类似div低级指令(我们在这里不谈论运算符重载)。
  • 我知道的所有硬件都使用U2。

所以。。。是否有任何行为(任何当代编译器,硬件)与上述行为不同?简单地说,我应该担心右移符号值没有转换为算术移位吗?

我的"解决方案"在许多平台上编译为一个低级指令,而其他平台则需要多个低级指令。你会在代码中使用什么?

请说实话;-)

为什么要担心符号类型>>中的"未定义行为"?

因为现在任何特定的未定义行为的定义有多好并不重要;关键是它可能会在未来的任何时候中断。您依赖于一种副作用,该副作用可能出于任何原因或无理由在任何时候被优化(或未优化)。

另外,在我使用我不应该

使用的东西之前,我不想问一个对许多不同编译器的实现有详细了解的人,所以我跳过了它。

是的,有些编译器的行为与您假设的不同。

特别是编译器中的优化阶段。它们利用变量的已知可能值,并将从不存在 UB 的情况下派生这些可能的值。如果指针已取消引用,则指针必须为非 null;如果整数用作除法器,则整数必须为非零;右移值必须为非负值。

这可以追溯到过去:

if (x<0) {
  printf("This is dead coden");
}
x >> 3;

真正归根结底是,你愿意冒险吗?

"标准不能保证亚达亚达"很好,但说实话,现在风险并不大。如果你打算在一些疯狂的平台上运行你的代码,你通常会提前知道。如果它让你感到惊讶,那么,这就是你承担的风险。

此外,解决方法很糟糕。如果你不需要它,它只是用毫无意义的"函数调用而不是右移"污染你的代码库,这将更难维护(因此会带来成本)。而且你永远无法将代码从其他地方"粘贴并忘记"到项目中 - 你总是必须检查代码是否有右移负有符号整数的可能性。