2010-10-12 36 views
10

我有一個四個無符號字符的數組。我想把它看作一個32位的數字(假設char的高位不關心,我只關心低8位)。然後,我想循環轉移它的任意數量的地方。我有幾個不同的換檔尺寸,都是在編譯時確定的。如何循環移位4個字符的數組?

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.我沒有指定一個平臺,讓你爲什麼假設一個?

+2

爲什麼不將其存儲在32位數據如int(取決於機器和所有)? – JoshD 2010-10-12 19:23:08

+0

如果字符是16位那麼你的例子是錯誤的,基本上你想要把它們當作8位字符,對吧? – 2010-10-12 21:05:23

回答

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

這看起來很有希望,讓我跑幾個測試用例。它比我的第一次嘗試更乾淨。 – 2010-10-12 20:01:42

+2

我看到你已經假設小端,但它可以很容易地修改爲大端。 – 2010-10-12 20:02:20

1

同時牢記純C的最佳方式是

inline void circular_left_shift(char *chars, short shift) { 
    __int32 *dword = (__int32 *)chars; 
    *dword = (*dword << shift) | (*dword >> (32 - shift)); 
} 

Uhmm,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

我會這樣做,但CHAR_BIT是16,因此在無符號字符[4]上面使用32位字進行別名不起作用。我不能依賴非標準的C功能,但感謝您的迴應。 – 2010-10-12 19:33:09

+0

剛剛修好。目標機器是什麼? – Keynslug 2010-10-12 19:54:48

+1

適用於TI DSP,其中int!= 32位,但我沒有看到代碼中的哪個位置無關緊要。這是否限制爲<= 7? – 2010-10-12 20:04:01

-1

使用union

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

它的安全(因爲指針別名),並更容易操縱。

編輯:你應該早些提到你的char不是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 
}; 
+1

+1使用'unsigned int',它實際上與問題中的測試數據一起使用。這與平臺上的排序無關嗎? – 2010-10-12 19:32:30

+2

請參閱我對之前答案的評論。 – 2010-10-12 19:33:57

+0

我看到你的編輯只是一個數組..我錯過了什麼? – 2010-10-12 20:04:50