¿Cómo hacer circular una matriz de 4 caracteres?

Tengo una serie de cuatro caracteres sin firmar. Quiero tratarlo como un número de 32 bits (suponga que a los bits superiores del carácter no les importa. Sólo me importan los 8 bits inferiores). Entonces, quiero cambiarlo circularmente por un número arbitrario de lugares. Tengo diferentes tamaños de turnos, todos determinados en tiempo de comstackción.

P.ej

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

Edición: A todos los que se preguntan por qué no mencioné CHAR_BIT! = 8, porque es el estándar C. No especifiqué una plataforma, entonces ¿por qué estás asumiendo una?

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

Obviamente

Mientras se tiene en cuenta el plano C, la mejor manera es

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

Uhmm, char tiene 16 bits de largo, no estaba claro para mí. Supongo que int es todavía 32 bits.

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

O simplemente podrías desconectar este ciclo.

Puede profundizar más en la instrucción de asm, en el x86 es capaz de realizar dicho cambio hasta los 31 bits restantes. Algo como un

 MOV CL, 31 ROR EAX, CL 

Utilizar union :

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

Es más seguro (debido al aliasing de punteros) y más fácil de manipular.

EDITAR: deberías haber mencionado antes que tu personaje no es de 8 bits. Sin embargo, esto debería hacer el truco:

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