首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >左移<<一空间

左移<<一空间
EN

Stack Overflow用户
提问于 2022-03-10 09:13:57
回答 1查看 187关注 0票数 -1

有没有办法做一个左移位位,并增加一个空格?

在c或c++中使用最少的操作数。

⚡My resolution

我没有具体说明我的需要是静态操作,也不需要动态操作。

在这种情况下,我选择了编译器宏。

代码语言:javascript
复制
#define EXPAND_2(bitmask)   (   ((bitmask & 0x0001) << 1)  |    /* Bit 0 expand    */ \
                                ((bitmask & 0x0002) << 2)  |    /* Bit 1 expand    */ \
                                ((bitmask & 0x0004) << 3)  |    /* Bit 2 expand    */ \
                                ((bitmask & 0x0008) << 4)  |    /* Bit 3 expand    */ \
                                ((bitmask & 0x0010) << 5)  |    /* Bit 4 expand    */ \
                                ((bitmask & 0x0020) << 6)  |    /* Bit 5 expand    */ \
                                ((bitmask & 0x0040) << 7)  |    /* Bit 6 expand    */ \
                                ((bitmask & 0x0080) << 8)  |    /* Bit 7 expand    */ \
                                ((bitmask & 0x0100) << 9)  |    /* Bit 8 expand    */ \
                                ((bitmask & 0x0200) << 10) |    /* Bit 9 expand    */ \
                                ((bitmask & 0x0400) << 11) |    /* Bit 10 expand   */ \
                                ((bitmask & 0x0800) << 12) |    /* Bit 11 expand   */ \
                                ((bitmask & 0x1000) << 13) |    /* Bit 12 expand   */ \
                                ((bitmask & 0x2000) << 14) |    /* Bit 13 expand   */ \
                                ((bitmask & 0x4000) << 15) |    /* Bit 14 expand   */ \
                                ((bitmask & 0x8000) << 16)      /* Bit 15 expand   */ \
                            )

该解决方案用于设置STM32的针模寄存器,其中每2位描述一位微控制器引脚的配置。

不管怎么说,即使邮件已经关闭,还是要谢谢你。

EN

回答 1

Stack Overflow用户

发布于 2022-03-10 09:34:24

如果要转换的数字范围有限,如4位,则使用查找表既简单又有效:

代码语言:javascript
复制
#include <stdint.h>

// For a 4-bit to 8-bit version:
uint8_t expand4(uint8_t v) {
    const static uint8_t table[16] = {
        0, 2, 8, 2+8, 32, 2+32, 8+32, 2+8+32,
        128, 2+128, 8+128, 2+8+128, 32+128, 2+32+128, 8+32+128, 2+8+32+128,
    };
    return table[v & 15];
}

// For a 8-bit to 16-bit version (counting on inline expansion):
uint16_t expand8(uint8_t v) {
    return (expand4(v >> 4) << 8) | expand4(v);
}

// For a 16-bit to 32-bit version (direct implementation):
uint32_t expand16(uint16_t v) {
    const static uint32_t t[16] = {
        0, 2, 8, 2+8, 32, 2+32, 8+32, 2+8+32,
        128, 2+128, 8+128, 2+8+128, 32+128, 2+32+128, 8+32+128, 2+8+32+128,
    };
    return t[v & 15] | (t[(v >> 4) & 15] << 8) | 
           (t[(v >> 8) & 15] << 16) | (t[(v >> 12) & 15] << 24);
}

使用更大的查找表可以减少指令的数量,但是初始化程序将更大,体积更大。

一个简单的循环可能会因为分支错误预测而降低效率:

代码语言:javascript
复制
#include <stdint.h>

uint32_t expand16(uint16_t v) {
    uint32_t res = 0;
    for (int shift = 1; v; v >>= 1, shift += 2) {
        res |= (v & 1) << shift;
    }
    return res;
}

这里还有另一种方法,没有班次或分支,但有许多摊档:

代码语言:javascript
复制
#include <stdint.h>

uint32_t expand16(uint16_t v) {
    uint32_t res = v;
    res += res & 0xFFF8000;
    res += res & 0xFFFC000;
    res += res & 0xFFFE000;
    res += res & 0xFFFF000;
    res += res & 0xFFFF800;
    res += res & 0xFFFFC00;
    res += res & 0xFFFFE00;
    res += res & 0xFFFFF00;
    res += res & 0xFFFFF80;
    res += res & 0xFFFFFC0;
    res += res & 0xFFFFFE0;
    res += res & 0xFFFFFF0;
    res += res & 0xFFFFFF8;
    res += res & 0xFFFFFFC;
    res += res & 0xFFFFFFE;
    return res + res;
}

将转移和增加相结合将改进这一方法,形成一种有效的解决方案:

代码语言:javascript
复制
#include <stdint.h>

uint32_t expand16(uint16_t v) {
    uint32_t res = ((uint32_t)v & 0xFF00) << 8) | (v & 0xFF);
    res = ((res & 0xF000F0) <<  4) | (res & 0xF000F);
    res += res & 0x08080808;
    res += res & 0x14141414;
    res += res & 0x2A2A2A2A;
    return res + res;  /* remove the last addition for expand_16_31 */
}
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/71421559

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档