【问题标题】:C, bit shift . 2 consecutive shiftsC、位移。 2个连续班次
【发布时间】:2013-01-30 06:37:26
【问题描述】:
static inline void ext4_ext_store_pblock(struct ext4_extent *ex,
                     ext4_fsblk_t pb)
{
    ex->ee_start_lo = cpu_to_le32((unsigned long) (pb & 0xffffffff));
    ex->ee_start_hi = cpu_to_le16((unsigned long) ((pb >> 31) >> 1) &
                      0xffff);
}

此代码来自 linux 内核。 见最后一行。它确实 pb>>31 然后 >>1 这和pb一样吗>> 32 为什么不这样做呢?

谢谢

编辑: 谢谢你们。将补丁发送到 ext4 邮件列表

【问题讨论】:

  • pb 是什么数据类型? IOW,ext4_fsblk_t 是什么?
  • typedef unsigned long long ext4_fsblk_t;
  • pb 保证至少为 64 位。因此,移动 32 位将不会调用未定义的行为。如果有的话,我不得不猜测编写该代码的人可能有点偏执,并且不确定标准的细节。
  • @Mysticial 或者,也许,部分代码曾经是 32 位的。
  • @AndersLind 如果讨论在邮件列表中弹出,如果你也在这里带来更新会很好。我刚刚在存档中找到了您的帖子,供有兴趣自己查找的人使用:news.gmane.org/…

标签: c


【解决方案1】:

这两种方法并不完全相同,具体取决于底层数据类型。该标准(C11,6.5.7 位移位运算符)规定:

如果右操作数的值为负数或大于或等于提升的左操作数的宽度,则行为未定义。

因此,如果要将 32 位宽的整数类型向右移动 32 位,则会导致未定义的行为。但是,将其移动 31 位,然后再移动另一位 定义良好。

这一点虽然是某人可能这样做的原因,但在这种特殊情况下可能没有实际意义。鉴于您的类型是 unsigned long long(保证 64 位宽度),(x >> 31) >> 1x >> 32 之间应该没有区别。

但是,如果某些平台实际上将 ext4_fsblk_t 定义为 32 位类型(或者如果它是从允许 32 位类型 (a) 的早期实现继承而来),您会发现自己不得不求助于两阶段转变来保证明确的行为。


(a)ext3ext4 之间有一个过渡阶段,允许 ext3 移动到 48 位及其范围,这是通往 @987654329 的垫脚石@ 及其 64 位数据类型。在此之前,8TB 是文件系统的实际限制。

可能,虽然我还没有证实,这段代码 sn-p 是该转换的遗留物,在基础数据类型达到 64 位宽之前。

开始使用的类型sector_t 有条件地定义为u64unsigned long,这可以解释为什么代码首先存在。在将其定义为后者的情况下,可能需要进行两阶段转换。

但是,鉴于ext4 已将这个临时阶段抛在脑后,我不确定是否还需要两阶段转变。最好的办法是提出更改请求,看看它是否被开发人员击落:-)

【讨论】:

  • 嗯,移位 31 位(对于带符号的 32 位整数)已经具有将符号位复制到所有位的效果。所以我看不到转移 32 岁的目的。
  • @Mystical:它是无符号的,所以应该是一个合乎逻辑的转变。我猜 long long 可能是 32 位,所以这是为了防止在这种情况下出现未定义的行为。
  • @Mystical,是的,这可能适用于有符号整数,但这里不一定是这种情况。
  • @GuySirton 哦,现在我看到了评论。这是一个unsigned long long。保证至少为 64 位。
  • @paxdiablo 好吧,最少的研究就会指出这一点。由于 ext4 定义了 64 位块号 (lxr.free-electrons.com/source/fs/ext4/ext4.h#L72) ext4_fsblk_t 不太可能被定义为 32 位类型,因为这会破坏 ext4 格式。
【解决方案2】:

我可以想象代码是从 ext3 复制的,其中 ext3_fsblk_t 定义为 unsigned long(32 位)。在这种情况下,paxdiablo 的论点是正确的:

标准(C11,6.5.7 位移位运算符)规定:

如果右操作数的值为负数或大于或等于提升的左操作数的宽度,则行为未定义。

因此,如果将 32 位整数向右移动 32 位,则它是未定义的。但是,将其移动 31 位,然后定义另一个位。

对于ext4_fsblk_t 定义为unsigned long longlong long 又是guaranteed to be 64 bit,此代码不再有意义。

【讨论】:

  • 虽然有一个配置选项可以为 ext2 和 ext3 使用 ext4 驱动程序,但不确定会产生什么影响
  • @technosaurus 因为这个选项显然不会改变 ext4_fsblk_t 的类型,我认为没有影响。但是 +1 指出了这一点。谢谢。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2022-10-23
  • 1970-01-01
  • 1970-01-01
  • 2021-07-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多