C,位移.连续2班

And*_*ind 9 c

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);
}
Run Code Online (Sandbox Code Playgroud)

这段代码来自linux内核.见最后一行.它确实pb >> 31然后>> 1这与pb相同>> 32为什么不这样做?

谢谢

编辑:谢谢大家.发送补丁到ext4 maillist

pax*_*blo 8

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

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

因此,如果要将32位宽整数类型32位向右移位,则会导致未定义的行为.然而,将它移位31位然后另一位明确定义的.

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

但是,如果某个平台实际上定义ext4_fsblk_t为32位类型(或者如果它是从允许32位类型(a)的早期实现中继承),那么您将发现自己不得不采用两阶段转换来保证定义的行为.


(a):在它之间有一个临时阶段ext3,ext4它允许ext3以其范围移动到48位,这是通往ext4其64位数据类型的一个垫脚石.在此之前,8TB是文件系统的实际限制.

这是可能的,虽然我还没有证实,这代码来自过渡宿醉,前基础数据类型广泛上升到64位.

将要使用的类型sector_t有条件地定义为u64或者unsigned long,这可以解释为什么代码首先存在.在将其定义为后者的情况下,可能需要两阶段的转变.

然而,鉴于ext4已经离开了这个临时阶段,我不确定是否需要进行两阶段转变.最好的办法是提出变更请求,看看它是否被开发人员击落:-)