我的问题与this one有关,并且几乎没有问题。
对我来说最明显的(意味着我会在我的代码中使用它)解决上述问题就是这样:
uint8_t x = some value;
x = (int8_t)x >> 7;
是的,是的,我听到你们所有人......未定义的行为,这就是为什么我没有发布我的“解决方案”。
我有一种感觉(也许只是我生病的头脑),术语“未定义的行为”在SO上被过度使用,只是为了证明如果问题被标记为c / c ++,那么就可以为某人辩护。
所以 - 让我们(暂时)抛开C / C ++标准,思考日常生活/编程,真正的编译器实现以及它们为现代硬件生成的代码。
考虑到以下因素:
>>
转换为有符号类型的算术移位和无符号类型的逻辑移位。div
- 就像在c / c ++代码中使用>>
时的低级指令一样(我们不是在讨论运算符重载)。所以...有什么(任何当代编译器,硬件)的行为与上面提到的不同?简单地说,我是否应该担心右移有符号值而不是转换为算术移位?
我的'解决方案'在许多平台上只编译一个低级指令,而其他平台则需要多个低级指令。你会在代码中使用什么?
请真相; - )
答案 0 :(得分:9)
为什么要担心>>中的'未定义的行为'?签名类型?
因为确定任何特定的未定义行为的定义并不重要现在;关键是它可能会在未来的任何时候破裂。您依赖于可能因任何原因或无理由而在任何时候被优化(或未优化)的副作用。
另外,在使用我不应该使用的东西之前,我不想要求有人详细了解许多不同编译器的实现,所以我跳过它。
答案 1 :(得分:2)
是的,有些编译器的行为与您的假设不同。
特别是编译器中的优化阶段。这些利用了已知的可变变量值,并将从缺少UB得出那些可能的值。如果指针被取消引用,则该指针必须为非空,如果整数必须为零,如果它被用作分频器,则右移位值必须为非负值。
这可以追溯到时间:
if (x<0) {
printf("This is dead code\n");
}
x >> 3;
答案 2 :(得分:0)
真正归结为,你愿意承担风险吗?
“标准不保证yada yada”很好,但是现在说实话,风险并不大。如果你要在一个疯狂的平台上运行你的代码,你通常会提前知道。如果它让你感到意外,那就是你冒的风险。
此外,解决方法很糟糕。如果您不需要它,它只是用无意义的“函数调用而不是右移”来污染您的代码库,这将更难维护(从而带来成本)。并且你永远无法将其他地方的代码“粘贴并忘记”到项目中 - 你总是必须检查代码是否有可能正确地移动负的有符号整数。