有没有办法做一个左移位位,并增加一个空格?
在c或c++中使用最少的操作数。

⚡My resolution
我没有具体说明我的需要是静态操作,也不需要动态操作。
在这种情况下,我选择了编译器宏。
#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位描述一位微控制器引脚的配置。
不管怎么说,即使邮件已经关闭,还是要谢谢你。
发布于 2022-03-10 09:34:24
如果要转换的数字范围有限,如4位,则使用查找表既简单又有效:
#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);
}使用更大的查找表可以减少指令的数量,但是初始化程序将更大,体积更大。
一个简单的循环可能会因为分支错误预测而降低效率:
#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;
}这里还有另一种方法,没有班次或分支,但有许多摊档:
#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;
}将转移和增加相结合将改进这一方法,形成一种有效的解决方案:
#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 */
}https://stackoverflow.com/questions/71421559
复制相似问题