C

时间:2016-03-21 05:55:52

标签: c pointers

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

我期待创建一个函数,它将执行28位的循环移位,同时忽略剩余的4位。

例如,我在* Buffer

中有以下内容

1111000011001100101010100000

假设我想要将28位的1位循环移位,使其成为

1110000110011001010101010000

我环顾四周,无法弄清楚如何获得移位,忽略最后4位,并且能够根据先前设置的变量移位1,2,3或4位在该计划中。

任何帮助都会粉碎!提前谢谢。

3 个答案:

答案 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在哪里获得了他的价值?您可能需要考虑字节序。