我有一个包含4个字节的unsigned char *Buffer
,但其中只有28个与我相关。
我期待创建一个函数,它将执行28位的循环移位,同时忽略剩余的4位。
例如,我在* Buffer
中有以下内容 1111000011001100101010100000
假设我想要将28位的1位循环移位,使其成为
1110000110011001010101010000
我环顾四周,无法弄清楚如何获得移位,忽略最后4位,并且能够根据先前设置的变量移位1,2,3或4位在该计划中。
任何帮助都会粉碎!提前谢谢。
答案 0 :(得分:1)
一次只有1位,但这会产生28位循环移位
uint32_t csl28(uint32_t value) {
uint32_t overflow_mask = 0x08000000;
uint32_t value_mask = 0x07FFFFFF;
return ((value & value_mask) << 1) | ((value & overflow_mask) >> 27);
}
uint32_t csr28(uint32_t value) {
uint32_t overflow_mask = 0x00000001;
uint32_t value_mask = 0x0FFFFFFE;
return ((value & value_mask) >> 1) | ((value & overflow_mask) << 27);
}
另一个版本,基于this article。这在任意宽的比特字段(宽度)内移动了任意比特数(计数)。要在23位宽的字段中左移一个值5位:rotl32(value,5,23);
uint32_t rotl32 (uint32_t value, uint32_t count, uint32_t width) {
uint32_t value_mask = ((uint32_t)~0) >> (CHAR_BIT * sizeof(value) - width);
const uint32_t mask = (width-1);
count &= mask;
return value_mask & ((value<<count) | (value>>( (-count) & mask )));
}
uint32_t rotr32 (uint32_t value, uint32_t count, uint32_t width) {
uint32_t value_mask = ((uint32_t)~0) >> (CHAR_BIT * sizeof(value) - width);
const uint32_t mask = (width-1);
count &= mask;
return value_mask & ((value>>count) | (value<<( (-count) & mask )));
}
以上函数假设该值存储在&#34;值&#34;
的低位#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
const char *uint32_to_binary(uint32_t x)
{
static char b[33];
b[0] = '\0';
uint32_t z;
for (z = 0x80000000; z > 0; z >>= 1)
{
strcat(b, ((x & z) == z) ? "1" : "0");
}
return b;
}
uint32_t reverse(uint32_t value)
{
return (value & 0x000000FF) << 24 | (value & 0x0000FF00) << 8 |
(value & 0x00FF0000) >> 8 | (value & 0xFF000000) >> 24;
}
int is_big_endian(void)
{
union {
uint32_t i;
char c[4];
} bint = {0x01020304};
return bint.c[0] == 1;
}
int main(int argc, char** argv) {
char b[] = { 0x98, 0x02, 0xCA, 0xF0 };
char *buffer = b;
//uint32_t num = 0x01234567;
uint32_t num = *((uint32_t *)buffer);
if (!is_big_endian()) {
num = reverse(*((uint32_t *)buffer));
}
num >>= 4;
printf("%x\n", num);
for(int i=0;i<5;i++) {
printf("%s\n", uint32_to_binary(num));
num = rotl32(num, 3, 28);
}
for(int i=0;i<5;i++) {
//printf("%08x\n", num);
printf("%s\n", uint32_to_binary(num));
num = rotr32(num, 3, 28);
}
unsigned char out[4];
memset(out, 0, sizeof(unsigned char) * 4);
num <<= 4;
if (!is_big_endian()) {
num = reverse(num);
}
*((uint32_t*)out) = num;
printf("[ ");
for (int i=0;i<4;i++) {
printf("%s0x%02x", i?", ":"", out[i] );
}
printf(" ]\n");
}
答案 1 :(得分:0)
首先,您屏蔽前四个最重要的位
*(buffer + 3) &= 0x0F;
然后,您可以执行剩余28位的循环移位x
位。
注意:这适用于小端架构(x86 Pc和大多数微控制器)
答案 2 :(得分:-1)
[...]包含4个字节,但只有28个[...]
我们得到了,但是......
我猜你错误输入了你的例子的第二个数字。或者你&#39;&#39;忽略&#39;&#39;&#39;从左侧和右侧4位,这样您实际上是对24位进行了逮捕?无论如何:
使用与中相同的原则 Circular shift in c。
之前需要将Buffer转换为32位算术类型。也许你需要uint32_t?
Buffer在哪里获得了他的价值?您可能需要考虑字节序。