【问题标题】:Bitshift and integer promotion?位移和整数提升?
【发布时间】:2011-03-29 18:39:04
【问题描述】:

通常,C 要求将二元运算符的操作数提升为更高级别操作数的类型。可以利用这一点来避免使用冗长的强制转换填充代码,例如:

if (x-48U<10) ...
y = x+0ULL << 40;

等等

但是,我发现,至少对于 gcc,这种行为不适用于位移。即

int x = 1;
unsigned long long y = x << 32ULL;

我希望右侧操作数的类型会导致左侧操作数提升为unsigned long long,以便移位成功。但是,gcc 会打印一个警告:

warning: left shift count >= width of type

gcc 是否损坏,或者标准是否对 bitshift 的类型提升规则做了一些例外?

【问题讨论】:

  • 不管警告如何,它会推广吗? (毕竟这只是一个警告)。
  • 你不能只使用一个简短的宏来产生详细的演员表吗?喜欢#define ULL(x) ((unsigned long long)x)
  • @Robert:不,它产生了一个无操作,就好像我写了普通的&lt;&lt;32。 @Borealid:是的,我可以,但我喜欢编写可以在任何地方(例如其他项目)复制和粘贴的代码,而不需要额外的定义/标题。我讨厌typedef unsigned int uint;之类的东西。
  • @R..:关于你所拥有的 typedef,请参阅 stdint.huint64_t 是一个 64 位无符号值。这可以移植到大多数平台。
  • @R..,我有理由确定前几天我刚刚在 C99 理性文档中读到了一些关于此的内容。我的回忆是,他们故意选择让 LHS 参与整数提升,而不是 RHS,因为 RHS 上的值只能与其左侧类型中的位数一样大,而不会陷入未定义的行为。跨度>

标签: c gcc standards bit-manipulation integer-promotion


【解决方案1】:

所谓的常用算术转换适用于许多二元运算符,但不是全部。例如,它们不适用于位移运算符、&&、||、逗号运算符和赋值运算符。这是移位运算符的规则:

6.5.7 ... 3 语义 ...
对每个操作数执行整数提升。结果的类型是提升的左操作数的类型。如果右操作数的值为负数或大于或等于提升的左操作数的宽度,则行为未定义。

【讨论】:

  • 谢谢,这就是我要找的。​​span>
【解决方案2】:

真正的麻烦在于,促销只适用于您的平台定义为int 的任何内容。正如其他一些答案所述,位移运算符会将左操作数提升为 int。然而,这里int 被定义为一个32 位的值。整数转换不会升级为long long(64 位)。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-08-09
    • 2011-05-05
    • 1970-01-01
    • 2016-12-15
    • 1970-01-01
    相关资源
    最近更新 更多