在C中4个字节内循环移位28位 [英] Circular shift 28 bits within 4 bytes in C

查看:89
本文介绍了在C中4个字节内循环移位28位的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个unsigned char *Buffer,其中包含4个字节,但其中只有28个与我有关.

I have an unsigned char *Buffer that contains 4 bytes, but only 28 of them are relevant to me.

我正在寻求创建一个函数,该函数将对28位进行循环移位,而忽略其余4位.

I am looking to create a function that will do a circular shift of the 28 bits while ignoring the remaining 4 bits.

例如,我在* Buffer中有以下内容

For example, I have the following within *Buffer

1111000011001100101010100000

说我想左移28位中的1位,使其变为

Say I want to left circular shift by 1 bit of the 28 bits, making it

1110000110011001010101010000

我环顾四周,我无法弄清楚如何进行移位,忽略后4位,并且能够根据之前设置的变量移位1、2、3或4位.程序.

I have looked around and I can't figure out how to get the shift, ignore the last 4 bits, and have the ability to shift either 1, 2, 3, or 4 bits depending on a variable set earlier in the program.

任何与此有关的帮助都将被粉碎!预先感谢.

Any help with this would be smashing! Thanks in advance.

推荐答案

一次仅1位,但这会进行28位循环移位

Only 1 bit at a time, but this does a 28 bit circular shift

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);
}

另一个版本,基于本文.这在任意宽的位字段(宽度)内移位任意数量的位(计数).在23位宽的字段中将值左移5位:rotl32(value,5,23);

Another version, based on this article. This shifts an artbitrary number of bits (count) within an arbitrarily wide bit field (width). To left shift a value 5 bits in a 23 bit wide field: 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 )));
}

以上功能假定值存储在值"的低位

The above functions assume the value is stored in the low order bits of "value"

#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");
}

这篇关于在C中4个字节内循环移位28位的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆