如何循环移动4个字符的数组?

时间:2010-10-12 19:20:38

标签: c

我有一个包含四个无符号字符的数组。我想把它当作一个32位数字(假设char的高位不关心。我只关心较低的8位)。然后,我想循环移动任意数量的地方。我有一些不同的班次大小,都是在编译时确定的。

E.g。

unsigned char a[4] = {0x81, 0x1, 0x1, 0x2};
circular_left_shift(a, 1);
/* a is now { 0x2, 0x2, 0x2, 0x5 } */

编辑:大家都在想我为什么没有提到CHAR_BIT!= 8,因为这是标准的C.我没有指定一个平台,那你为什么假设一个?

3 个答案:

答案 0 :(得分:5)

static void rotate_left(uint8_t *d, uint8_t *s, uint8_t bits)
{
   const uint8_t octetshifts = bits / 8;
   const uint8_t bitshift = bits % 8;
   const uint8_t bitsleft = (8 - bitshift);
   const uint8_t lm = (1 << bitshift) - 1;
   const uint8_t um = ~lm;
   int i;

   for (i = 0; i < 4; i++)
   {
       d[(i + 4 - octetshifts) % 4] =
           ((s[i] << bitshift) & um) | 
           ((s[(i + 1) % 4] >> bitsleft) & lm);
   }
}   

显然

答案 1 :(得分:1)

虽然记住简单的C,但最好的方法是

inline void circular_left_shift(char *chars, short shift) {
    __int32 *dword = (__int32 *)chars;
    *dword = (*dword << shift) | (*dword >> (32 - shift));
}
嗯,char长16位,对我来说并不清楚。我认为int仍然是32位。

inline void circular_left_shift(char *chars, short shift) {
    int i, part;
    part = chars[0] >> (16 - shift);
    for (i = 0; i < 3; ++i)
        chars[i] = (chars[i] << shift) | (chars[i + 1] >> (16 - shift));
    chars[3] = (chars[3] << shift) | part;
}

或者你可以解开这个循环。

你可以进一步深入到asm指令ror,在x86上它能够执行这样的移位,最多可以保留31位。像

这样的东西
MOV CL, 31
ROR EAX, CL

答案 2 :(得分:-1)

使用union

typedef union chr_int{
   unsigned int  i;
   unsigned char c[4];
};

它更安全(因为指针别名)并且更容易操作。

编辑:你之前应该提到你的字符不是8位。但是,这应该可以解决问题:

#define ORIG_MASK 0x81010102
#define LS_CNT 1

unsigned char a[4] = { 
    ((ORIG_MASK <<  LS_CNT      ) | (ORIG_MASK >> (32 - LS_CNT))) & 0xff,
    ((ORIG_MASK << (LS_CNT +  8)) | (ORIG_MASK >> (24 - LS_CNT))) & 0xff,
    ((ORIG_MASK <<  LS_CNT + 16)) | (ORIG_MASK >> (16 - LS_CNT))) & 0xff,
    ((ORIG_MASK << (LS_CNT + 24)) | (ORIG_MASK >> ( 8 - LS_CNT))) & 0xff
};