c语言 读取字节,c – 从字节获取位

(src >> start) & ((1UL << len)-1) // or 1ULL << if you need a 64-bit mask

但是,如果len是该类型的整个宽度,则两种生产掩模的方式看起来都很冒险. (提取所有位的角落情况).按类型的整个宽度移位可以产生零或不变. (它实际上调用了未定义的行为,但实际上如果编译器在编译时看不到它会发生什么.例如,x86将移位计数屏蔽到0-31范围(对于32位移位).使用32位整数:

>如果1 <<< 32产生1,然后1-1 = 0,因此结果将为零.

>如果~0<< 32产生〜0,而不是0,掩码将为零.

请记住1< len是未定义的行为,因为它太大了:不像把它写成0x3ffffffffff或其他什么,没有自动升级到long long,所以1的类型很重要. 我想从你的例子中你想要的是位[iStartPos:iStartPos – iNumOfBites],其中位从零开始编号. 我在函数中改变的主要是函数和变量的命名,并添加注释.

> bitResult是函数的输入;不要在名称中使用“结果”.

> iStartPos好,但有点冗长

> iNumOfBites计算机具有位和字节.如果您正在处理叮咬,您需要医生(或牙医).

此外,返回类型可能应该是无符号的.

// extract bits [msb : msb-len] from input into the low bits of the result

unsigned BitExtract(unsigned input,int msb,int len)

{

return (input >> (msb-len + 1)) & ~(~0 << len);

}

如果你的起始位置参数是lsb而不是msb,表达式会更简单,代码会更小更快(除非这只会给调用者带来额外的工作).使用LSB作为参数,BitExtract是7条指令,如果它是MSB,则为9条(在x86-64,gcc 5.2上).

还有一个机器指令(与Intel Haswell和AMD Piledriver一起引入)执行此操作.使用它可以获得更小,更快的代码.它还使用LSB,len位置约定,而不是MSB,因此您可以使用LSB作为参数获得更短的代码.

Intel cpu只知道需要先将一个立即加载到寄存器中的版本,所以当这些值是编译时常量时,与简单的移位和屏蔽相比,它不会节省太多. e.g. see this post about using it or pextr for RGB32 -> RGB16.当然,如果start和len都是编译时常数,那么参数是否是所需范围的MSB或LSB无关紧要.

只有AMD实现了一个版本的bextr,它可以将控制掩码作为一个直接常量,但不幸的是,似乎gcc 5.2不使用立即版本来使用内在的代码(即使用-march = bdver2(即推土机v2也称为打桩机) ).(generate bextr with an immediate argument on its own in some cases与-march = bdver2.)

#include

// Intel ICC uses different intrinsics for bextr

// extract bits [msb : msb-len] from input into the low bits of the result

unsigned BitExtract(unsigned input,int len)

{

#ifdef __BMI__ // probably also need to check for __GNUC__

return __builtin_ia32_bextr_u32(input,(len<<8) | (msb-len+1) );

#else

return (input >> (msb-len + 1)) & ~(~0 << len);

#endif

}

需要额外的指令(movzx)来实现(msb-len 1)& 0xff安全检查,以避免起始字节溢出到长度字节中.我把它排除在外因为要求0-31范围之外的起始位是毫无意义的,更不用说0-255范围了.既然它不会崩溃,只返回一些其他废话结果,没有多大意义.

无论如何,bext保存了不少指令(如果BMI2 shlx / shrx也不可用!-march = godbolt上的native是Haswell,因此也包括BMI2.)

但是英特尔cpu上的bextr解码为2 uop(http://agner.org/optimize/),因此除了保存一些代码大小之外,它与shrx /并不是很有用. pext实际上更好的吞吐量(1 uop / 3c延迟),即使它是一种更强大的指令.但是,延迟更糟糕. AMD cpu运行速度非常慢,但bextr作为单个uop.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值