You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C语言:拼接不同long类型数据的部分位及实现指定位提取函数

嘿,这可是个典型的位操作问题,我一步步给你拆解清楚——先解决第一个拼接long类型部分内容的问题,再实现你要的getbits函数。

一、在C语言中拼接不同long类型的部分内容

核心就是用好三个位操作工具:

  • 掩码(&):用来精准提取你需要的位段。比如要从一个unsigned long里取低12位,就用value & 0xFFF;要取第20到27位(共8位),就先把数值右移20位,再用& 0xFF过滤出低8位:(value >> 20) & 0xFF。
  • 移位(<<、>>):把提取到的位段挪到目标位置。比如刚才取的低12位要放到结果的高12位,就用low_12_bits << (64 - 12)(假设是64位unsigned long)。
  • 按位或(|):把不同的位段拼接成一个完整的数值。比如把高16位和低48位拼起来:(high_16_bits << 48) | low_48_bits。

举个简单例子:假设我们有两个64位unsigned long变量a和b,要把a的高32位和b的低32位拼成新的unsigned long:

unsigned long a = 0xABCDEF001234567A;
unsigned long b = 0x98761111FCDFEC80;
unsigned long result = (a & 0xFFFFFFFF00000000) | (b & 0x00000000FFFFFFFF);

二、实现getbits函数

先从你的示例反推规则:

  • 数组bits是连续的位序列,bits[0]是高64位,bits[1]是低64位;
  • 位编号从0开始,第0位是整个序列的最低位(LSB)(也就是bits[1]的第0位);
  • 调用getbits(bits, 56, 20)要返回0x0000000000067A98,这意味着我们要提取从第56位到第75位的20位,这20位跨了bits[1]的56-63位(8位)和bits[0]的0-11位(12位),拼接后得到目标值。

基于这个逻辑,写出的函数如下:

#include <stddef.h>

unsigned long getbits(unsigned long bits[], unsigned idx, unsigned len) {
    unsigned end_idx = idx + len - 1;
    // 这里假设数组固定为2个元素,如果要支持任意长度,可以添加数组长度参数
    const size_t array_len = 2;
    // 计算起始位和结束位所在的数组元素索引
    size_t start_elem = array_len - 1 - (idx / 64);
    size_t end_elem = array_len - 1 - (end_idx / 64);
    
    unsigned long result = 0;
    
    if (start_elem == end_elem) {
        // 所有位都在同一个元素中
        unsigned shift = idx % 64;
        // 生成len位全1的掩码,注意用1UL避免溢出(len=64时用~0UL)
        unsigned long mask = (len == 64) ? ~0UL : ((1UL << len) - 1);
        result = (bits[start_elem] >> shift) & mask;
    } else {
        // 跨两个元素提取(示例就是这种情况)
        // 提取低位元素的目标部分(从idx到该元素的最高位)
        unsigned low_bits_len = 64 - (idx % 64);
        unsigned long low_part = bits[start_elem] >> (idx % 64);
        
        // 提取高位元素的目标部分(从该元素的最低位到end_idx)
        unsigned high_bits_len = len - low_bits_len;
        unsigned long high_part = bits[end_elem] & ((1UL << high_bits_len) - 1);
        
        // 拼接两部分:高位部分左移低位长度,再和低位部分按位或
        result = (high_part << low_bits_len) | low_part;
    }
    
    return result;
}

验证示例:

把bits = {0xABCDEF001234567A, 0x98761111FCDFEC80}传入函数:

  • idx=56,len=20,end_idx=75;
  • start_elem=1(对应bits[1]),end_elem=0(对应bits[0]);
  • 从bits[1]提取56-63位:0x98761111FCDFEC80 >>56得到0x98;
  • 从bits[0]提取0-11位:0xABCDEF001234567A & 0xFFF得到0x67A;
  • 拼接:(0x67A <<8) | 0x98 = 0x67A98,和示例预期结果一致。

补充说明:

  1. 如果你的数组存储顺序相反(bits[0]是低64位),只需要调整start_elem和end_elem的计算方式,改成start_elem = idx /64即可;
  2. 如果需要支持len超过64位的情况,可以添加循环处理多个元素的逻辑;
  3. 代码中用1UL而不是1,是为了避免int类型左移溢出的问题,确保位操作在unsigned long的范围内进行。

内容的提问来源于stack exchange,提问作者Vegas

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.21 07:28:42