find_next_zero_bit 函数

本文介绍了一种用于查找内存中下一个零位(bit)位置的高效算法。通过位运算和循环处理,该算法能够快速定位到指定偏移量之后的第一个零位,适用于多种应用场景,如位图(bitmap)管理和内存分配。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

unsigned long find_next_zero_bit(const unsigned long *addr, unsigned long size,
        unsigned long offset)
{
    const unsigned long *p = addr + BITOP_WORD(offset); // offset位于p指向的long地址32位空间
    unsigned long result = offset & ~(BITS_PER_LONG-1); // offset是第result个4字节
    unsigned long tmp;

    if (offset >= size)
        return size;
    size -= result;                                     // 调整32位整倍数上
    offset %= BITS_PER_LONG;                            // offset位于32位的第几位
    if (offset) {                                       // offset不在一个long数据的第0位上,在1-31位中[luther.gliethttp]
        tmp = *(p++);
        tmp |= ~0UL >> (BITS_PER_LONG - offset);        // 将0-offset数据填充上1.
        if (size < BITS_PER_LONG)                       // 不足32bits
            goto found_first;
        if (~tmp)                                       // 取非非0说明含有0值
            goto found_middle;
        size -= BITS_PER_LONG;                          // 如果上面~tmp等于0,那么说明该*p数据为32位全1.[luther.gliethttp]
        result += BITS_PER_LONG;
    }
    while (size & ~(BITS_PER_LONG-1)) {                 // 好了,执行到这里,我们的offset已经处在4字节的第0位上,下面进行
        if (~(tmp = *(p++)))                            // 4字节快速查询.如果~tmp非0,说明该32位数据中含有0数据,找到.[luther.gliethttp]
            goto found_middle;
        result += BITS_PER_LONG;                        // 到下一个4字节空间
        size -= BITS_PER_LONG;                          // 减少4字节数据
    }
    if (!size)                                          // size等于0,说明首先size等于4字节整倍数,其次所有数据已经查完,
        return result;                                  // 所有数据全部为1,没有发现0位,result等于size.[luther.gliethttp]
    tmp = *p;                                           // size不是32位整倍数,还剩几个bit没有检查,继续执行下面检查工作.[luther.gliethtp]

found_first:
    tmp |= ~0UL << size;                                // 现在0-size为有效数据,size-31为未使用空间,所以先将size-31置成全1.
    if (tmp == ~0UL)    /* Are any bits zero? */        // 如果tmp全1,那么说明就没找找1个
        return result + size;    /* Nope. */             // result+size就等于函数传入的参数size大小.[luther.gliethttp]
found_middle:
    return result + ffz(tmp);                           // 我们在32位数据的0-31中发现必定存在0位值,计算他是第几位.[luther.gliethttp]
}

#define ffz(x)  __ffs(~(x))                             // __ffs找到第一次出现1值的偏移值,从bit0开始到bit31依次找[luther.gliethttp]
/**
 * __ffs - find first bit in word.
 * @word: The word to search
 *
 * Undefined if no bit exists, so code should check against 0 first.
 */
static inline unsigned long __ffs(unsigned long word)
{
    int num = 0;

#if BITS_PER_LONG == 64
    if ((word & 0xffffffff) == 0) {
        num += 32;
        word >>= 32;
    }
#endif
    if ((word & 0xffff) == 0) {                         // 低16位没有1值,那么num加16,同时高16位移动到低16位
        num += 16;                                      // 这样低16位永远都是去掉根本不存在的那种必然情况后的数据.
        word >>= 16;
    }
    if ((word & 0xff) == 0) {                           // 低8位是否有
        num += 8;
        word >>= 8;
    }
    if ((word & 0xf) == 0) {
        num += 4;
        word >>= 4;
    }
    if ((word & 0x3) == 0) {
        num += 2;
        word >>= 2;
    }
    if ((word & 0x1) == 0)
        num += 1;
    return num;                                         // 这样num就是出现1的偏移值了.[luther.gliethttp]
}
1、我输入C语言代码后无法解析,也就是点击解析代码没有反映,而且typedef unsigned char U1; typedef unsigned short U2; typedef unsigned long U4; typedef signed char S1; typedef signed short S2; typedef signed long S4;这些是已经定义好的,我在输入代码时只会输入一段代码比如static void Diag21_PID_C9(U1 u1_a_num) { U1 u1_t_data[PID21_DL_C9]; U1 u1_t_cmplt; U1 u1_t_flag; U1 u1_t_cnt; U1 u1_t_swrstcnt; U2 u2_t_buf[DIAG21_PIDC9_FLAG]; U4 u4_t_data; U4 u4_t_cmd; U1 u1_t_sndbuf_21[PID21_SENDDL_C9]; vd_g_Diagmgr_Set_Insp_Indx((U1)U1_MAX); u1_t_flag = (U1)DIAG21_ZERO; u4_t_data = (U4)DIAG21_ZERO; u1_t_swrstcnt = u1_g_Diagmgr_Get_SwRst_Cnt(); if((U1)DIAG_CNT_ZERO == u1_t_swrstcnt) /* Determine if a software reset is in progress */ { for(u1_t_cnt = (U1)DIAG21_ZERO; u1_t_cnt < (U1)DIAG21_PIDC9_FLAG; u1_t_cnt ++) { u4_t_cmd = u4_InspIndx_To_InspCMD[DIAG21_C9_INDX] + (U4)((U4)u1_t_cnt << (U4)DIAG21_BIT_SHIFT8); u1_t_cmplt = u1_g_InspSoftwareVersion(u4_t_cmd, &u4_t_data, (U1)TRUE); if((U1)INSPECT_SRV_CMPLT == u1_t_cmplt) { u1_t_flag = u1_t_flag + (U1)DIAG21_CNTONE; } else { /* Do Nothing */ } u2_t_buf[u1_t_cnt] = (U2)u4_t_data; } vd_s_Diag21_U2ToU1(u2_t_buf, u1_t_data, (U1)DIAG21_PIDC9_FLAG); vd_DG_COPY_U1(&u1_t_sndbuf_21[SND21_DATA1], &u1_t_data[0], (U1)PID21_DL_C9); if((U1)DIAG21_PIDC9_FLAG == u1_t_flag) { u1_t_sndbuf_21[SND21_PID] = (U1)DIAG21_ID_C9; DiagmgrSendResponse((U1)ID_MODE21, (U1)PID21_SENDDL_C9, u1_t_sndbuf_21, (U1)FALSE); } else { /* Do Nothing */ } } else { /* Do Nothing */ } } 2、增加进度条的功能 3、增加日志功能
最新发布
07-17
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值