Related
Problem: swap alternate bytes as below:
Input: uint8_t buf[4] = {0xab,0xcd,0xef,0xba};
Output: 0xcdababef
I have the below code for doing that but I am wondering if there is any better way to shorten the code.
#include <stdint.h>
#define SWAP_16(buf) (((buf & 0xFF00) >> 8) | ((buf & 0x00FF) << 8))
int main()
{
unsigned int value;
int i, j=0;
uint8_t buf[4] = {0,4,0,0};
unsigned int mask = 0xFFFF;
unsigned int tmp_value;
unsigned int size = 4;
for (i = size - 1 ;i >= 0; i--) {
tmp_value |= (buf[j] << 8*i);
j++;
}
value = SWAP_16((tmp_value & (mask << 16)) >> 16) << 16 |
SWAP_16(tmp_value & mask);
return 0;
}
Assuming unsigned int is 32-bits, you can simply use:
value = ((value & 0xff00ff00) >> 8) | ((value & 0x00ff00ff) << 8);
to swap the bytes in each pair of bytes in value. It's similar to your SWAP_16() macro except that it does both halves of the value at once.
unsigned int forward = 0x12345678;
unsigned int reverse;
unsigned char *f = &forward;
unsigned char *r = &reverse;
r[0]=f[3];
r[1]=f[2];
r[2]=f[1];
r[3]=f[0];
now reverse will be 0x78563412
Here is one way:
#include <stdio.h>
#include <stdint.h>
int main(void)
{
uint8_t buf[4] = {0xab,0xcd,0xef,0xba};
unsigned int out = buf[1] * 0x1000000u + buf[0] * 0x10000u + buf[3] * 0x100u + buf[2];
printf("%x\n", out);
}
It's not immediately clear from your question if it's not an option, but you could merely just swap the bytes in the array if you know the size won't change:
#include <stdio.h>
#include <stdint.h>
#define SWAPPED(b) { b[1], b[0], b[3], b[2] }
#define PRINT(b) printf("0x0%x\n", *((uint32_t*)b));
int main()
{
uint8_t buf[4] = {8,4,6,1};
uint8_t swapped[4] = SWAPPED(buf);
PRINT(buf);
PRINT(swapped);
return 0;
}
The output for this on my machine is:
0x01060408
0x06010804
This is because of endian-ness and printing an array casted to an integer type, but the bytes are swapped as you ask in your question.
Hope that helps.
Use a union
#include <stdint.h>
#define SWAP_VAR(T, v1, v2) do { \
T v = (v1); \
(v1) = (v2); \
(v2) = v; \
} while (0);
union U32
{
uint32_t u;
unsigned char a[4];
};
uint32_t swap32(uint32_t u)
{
union U32 u32 = {u};
SWAP_VAR(unsigned char, u32.a[0], u32.a[1]);
SWAP_VAR(unsigned char, u32.a[2], u32.a[3]);
return u32.u;
}
Use it like this:
#include <stdint.h>
uint32_t swap32(uint32_t u);
int main(void)
{
uint32_t u = 0x12345678;
u = swap32(u);
}
unsigned int n = ((unsigned int)buf[0] << 16) |
((unsigned int)buf[1] << 24) |
((unsigned int)buf[2] << 0) |
((unsigned int)buf[3] << 8);
This question already has answers here:
Why are these constructs using pre and post-increment undefined behavior?
(14 answers)
Closed 8 years ago.
Guys i have next two pieces of code which extracts 32bit variable from 8bit
1) First is that:
#include <stdio.h>
#include <string.h>
int main()
{
unsigned char buffer[] = {0xaa, 0xbb, 0xcc, 0xdd, 0xee};
unsigned char *buff = buffer;
unsigned int result;
result = *buff++;
result += *buff++ <<8;
result += *buff++ << 16;
result += *buff++ <<24;
printf("result = 0x%x, *buffer = 0x%x.", result, *buff);
return 0;
}
Without any warning, but it looks a little lame....
2) In second we have macro instead of those ugly 4 lines:
#include <stdio.h>
#include <string.h>
#define to32(buffer) ((unsigned int)*buffer++ | *buffer++ << 8 | *buffer++ << 16 | *buffer++ << 24)
int main()
{
unsigned char buffer[] = {0xaa, 0xbb, 0xcc, 0xdd, 0xee};
unsigned char *buff = buffer;
unsigned int result = to32(buff);
printf("result = 0x%x, *buffer = 0x%x.", result, *buff);
return 0;
}
And it leaves next warning:
main.cpp: In function 'int main()':
main.cpp:4:99: warning: operation on 'buff' may be undefined [-Wsequence-point]
#define to32(buffer) ((unsigned int)*buffer++ | *buffer++ << 8 | *buffer++ << 16 | *buffer++ << 24)
And i'm little confused what's exactly GCC found as undefined behavior.
Is it that all shifts in one line and i sum it?
EDIT
A solution is:
static inline unsigned to32(const unsigned char *buffer)
{
return buffer[0] | buffer[1] << 8 | buffer[1] << 16 | buffer[3] << 24;
}
If you really don't like functions, you can do the same with a macro...
It is about those sequence-points the compiler warns you about.
The order is not defined here:
to32(buffer) ((unsigned int)*buffer++ | *buffer++ << 8 | *buffer++ << 16 | *buffer++ << 24)
// will be
buffer = *buffer++;
buffer |= *buffer++ << 8;
....
// or
buffer = *buffer++ << 8;
buffer |= *buffer++;
...
In case of || and && there is a sequence point at the operator, and the operations have an order, going left to right. But not at | and &
The order is not defined, the compiler can do it any order.
After some suggestions from Buella Gabor and auguar it came to me that i can do it like that.
And it seems to be right
#define to32(buffer) ((unsigned int)*buffer | *(buffer+1) << 8 | *(buffer+2) << 16 | *(buffer+3) << 24)
Though it's not perfect for my needs :(
I just want to ask if my method is correct to convert from little endian to big endian, just to make sure if I understand the difference.
I have a number which is stored in little-endian, here are the binary and hex representations of the number:
0001 0010 0011 0100 0101 0110 0111 1000
12345678
In big-endian format I believe the bytes should be swapped, like this:
1000 0111 0110 0101 0100 0011 0010 0001
87654321
Is this correct?
Also, the code below attempts to do this but fails. Is there anything obviously wrong or can I optimize something? If the code is bad for this conversion can you please explain why and show a better method of performing the same conversion?
uint32_t num = 0x12345678;
uint32_t b0,b1,b2,b3,b4,b5,b6,b7;
uint32_t res = 0;
b0 = (num & 0xf) << 28;
b1 = (num & 0xf0) << 24;
b2 = (num & 0xf00) << 20;
b3 = (num & 0xf000) << 16;
b4 = (num & 0xf0000) << 12;
b5 = (num & 0xf00000) << 8;
b6 = (num & 0xf000000) << 4;
b7 = (num & 0xf0000000) << 4;
res = b0 + b1 + b2 + b3 + b4 + b5 + b6 + b7;
printf("%d\n", res);
OP's sample code is incorrect.
Endian conversion works at the bit and 8-bit byte level. Most endian issues deal with the byte level. OP's code is doing a endian change at the 4-bit nibble level. Recommend instead:
// Swap endian (big to little) or (little to big)
uint32_t num = 9;
uint32_t b0,b1,b2,b3;
uint32_t res;
b0 = (num & 0x000000ff) << 24u;
b1 = (num & 0x0000ff00) << 8u;
b2 = (num & 0x00ff0000) >> 8u;
b3 = (num & 0xff000000) >> 24u;
res = b0 | b1 | b2 | b3;
printf("%" PRIX32 "\n", res);
If performance is truly important, the particular processor would need to be known. Otherwise, leave it to the compiler.
[Edit] OP added a comment that changes things.
"32bit numerical value represented by the hexadecimal representation (st uv wx yz) shall be recorded in a four-byte field as (st uv wx yz)."
It appears in this case, the endian of the 32-bit number is unknown and the result needs to be store in memory in little endian order.
uint32_t num = 9;
uint8_t b[4];
b[0] = (uint8_t) (num >> 0u);
b[1] = (uint8_t) (num >> 8u);
b[2] = (uint8_t) (num >> 16u);
b[3] = (uint8_t) (num >> 24u);
[2016 Edit] Simplification
... The type of the result is that of the promoted left operand.... Bitwise shift operators C11 §6.5.7 3
Using a u after the shift constants (right operands) results in the same as without it.
b3 = (num & 0xff000000) >> 24u;
b[3] = (uint8_t) (num >> 24u);
// same as
b3 = (num & 0xff000000) >> 24;
b[3] = (uint8_t) (num >> 24);
Sorry, my answer is a bit too late, but it seems nobody mentioned built-in functions to reverse byte order, which in very important in terms of performance.
Most of the modern processors are little-endian, while all network protocols are big-endian. That is history and more on that you can find on Wikipedia. But that means our processors convert between little- and big-endian millions of times while we browse the Internet.
That is why most architectures have a dedicated processor instructions to facilitate this task. For x86 architectures there is BSWAP instruction, and for ARMs there is REV. This is the most efficient way to reverse byte order.
To avoid assembly in our C code, we can use built-ins instead. For GCC there is __builtin_bswap32() function and for Visual C++ there is _byteswap_ulong(). Those function will generate just one processor instruction on most architectures.
Here is an example:
#include <stdio.h>
#include <inttypes.h>
int main()
{
uint32_t le = 0x12345678;
uint32_t be = __builtin_bswap32(le);
printf("Little-endian: 0x%" PRIx32 "\n", le);
printf("Big-endian: 0x%" PRIx32 "\n", be);
return 0;
}
Here is the output it produces:
Little-endian: 0x12345678
Big-endian: 0x78563412
And here is the disassembly (without optimization, i.e. -O0):
uint32_t be = __builtin_bswap32(le);
0x0000000000400535 <+15>: mov -0x8(%rbp),%eax
0x0000000000400538 <+18>: bswap %eax
0x000000000040053a <+20>: mov %eax,-0x4(%rbp)
There is just one BSWAP instruction indeed.
So, if we do care about the performance, we should use those built-in functions instead of any other method of byte reversing. Just my 2 cents.
I think you can use function htonl(). Network byte order is big endian.
"I swap each bytes right?" -> yes, to convert between little and big endian, you just give the bytes the opposite order.
But at first realize few things:
size of uint32_t is 32bits, which is 4 bytes, which is 8 HEX digits
mask 0xf retrieves the 4 least significant bits, to retrieve 8 bits, you need 0xff
so in case you want to swap the order of 4 bytes with that kind of masks, you could:
uint32_t res = 0;
b0 = (num & 0xff) << 24; ; least significant to most significant
b1 = (num & 0xff00) << 8; ; 2nd least sig. to 2nd most sig.
b2 = (num & 0xff0000) >> 8; ; 2nd most sig. to 2nd least sig.
b3 = (num & 0xff000000) >> 24; ; most sig. to least sig.
res = b0 | b1 | b2 | b3 ;
You could do this:
int x = 0x12345678;
x = ( x >> 24 ) | (( x << 8) & 0x00ff0000 )| ((x >> 8) & 0x0000ff00) | ( x << 24) ;
printf("value = %x", x); // x will be printed as 0x78563412
One slightly different way of tackling this that can sometimes be useful is to have a union of the sixteen or thirty-two bit value and an array of chars. I've just been doing this when getting serial messages that come in with big endian order, yet am working on a little endian micro.
union MessageLengthUnion
{
uint16_t asInt;
uint8_t asChars[2];
};
Then when I get the messages in I put the first received uint8 in .asChars[1], the second in .asChars[0] then I access it as the .asInt part of the union in the rest of my program.
If you have a thirty-two bit value to store you can have the array four long.
I am assuming you are on linux
Include "byteswap.h" & Use int32_t bswap_32(int32_t argument);
It is logical view, In actual see, /usr/include/byteswap.h
one more suggestion :
unsigned int a = 0xABCDEF23;
a = ((a&(0x0000FFFF)) << 16) | ((a&(0xFFFF0000)) >> 16);
a = ((a&(0x00FF00FF)) << 8) | ((a&(0xFF00FF00)) >>8);
printf("%0x\n",a);
A Simple C program to convert from little to big
#include <stdio.h>
int main() {
unsigned int little=0x1234ABCD,big=0;
unsigned char tmp=0,l;
printf(" Little endian little=%x\n",little);
for(l=0;l < 4;l++)
{
tmp=0;
tmp = little | tmp;
big = tmp | (big << 8);
little = little >> 8;
}
printf(" Big endian big=%x\n",big);
return 0;
}
OP's code is incorrect for the following reasons:
The swaps are being performed on a nibble (4-bit) boundary, instead of a byte (8-bit) boundary.
The shift-left << operations of the final four swaps are incorrect, they should be shift-right >> operations and their shift values would also need to be corrected.
The use of intermediary storage is unnecessary, and the code can therefore be rewritten to be more concise/recognizable. In doing so, some compilers will be able to better-optimize the code by recognizing the oft-used pattern.
Consider the following code, which efficiently converts an unsigned value:
// Swap endian (big to little) or (little to big)
uint32_t num = 0x12345678;
uint32_t res =
((num & 0x000000FF) << 24) |
((num & 0x0000FF00) << 8) |
((num & 0x00FF0000) >> 8) |
((num & 0xFF000000) >> 24);
printf("%0x\n", res);
The result is represented here in both binary and hex, notice how the bytes have swapped:
0111 1000 0101 0110 0011 0100 0001 0010
78563412
Optimizing
In terms of performance, leave it to the compiler to optimize your code when possible. You should avoid unnecessary data structures like arrays for simple algorithms like this, doing so will usually cause different instruction behavior such as accessing RAM instead of using CPU registers.
#include <stdio.h>
#include <inttypes.h>
uint32_t le_to_be(uint32_t num) {
uint8_t b[4] = {0};
*(uint32_t*)b = num;
uint8_t tmp = 0;
tmp = b[0];
b[0] = b[3];
b[3] = tmp;
tmp = b[1];
b[1] = b[2];
b[2] = tmp;
return *(uint32_t*)b;
}
int main()
{
printf("big endian value is %x\n", le_to_be(0xabcdef98));
return 0;
}
You can use the lib functions. They boil down to assembly, but if you are open to alternate implementations in C, here they are (assuming int is 32-bits) :
void byte_swap16(unsigned short int *pVal16) {
//#define method_one 1
// #define method_two 1
#define method_three 1
#ifdef method_one
unsigned char *pByte;
pByte = (unsigned char *) pVal16;
*pVal16 = (pByte[0] << 8) | pByte[1];
#endif
#ifdef method_two
unsigned char *pByte0;
unsigned char *pByte1;
pByte0 = (unsigned char *) pVal16;
pByte1 = pByte0 + 1;
*pByte0 = *pByte0 ^ *pByte1;
*pByte1 = *pByte0 ^ *pByte1;
*pByte0 = *pByte0 ^ *pByte1;
#endif
#ifdef method_three
unsigned char *pByte;
pByte = (unsigned char *) pVal16;
pByte[0] = pByte[0] ^ pByte[1];
pByte[1] = pByte[0] ^ pByte[1];
pByte[0] = pByte[0] ^ pByte[1];
#endif
}
void byte_swap32(unsigned int *pVal32) {
#ifdef method_one
unsigned char *pByte;
// 0x1234 5678 --> 0x7856 3412
pByte = (unsigned char *) pVal32;
*pVal32 = ( pByte[0] << 24 ) | (pByte[1] << 16) | (pByte[2] << 8) | ( pByte[3] );
#endif
#if defined(method_two) || defined (method_three)
unsigned char *pByte;
pByte = (unsigned char *) pVal32;
// move lsb to msb
pByte[0] = pByte[0] ^ pByte[3];
pByte[3] = pByte[0] ^ pByte[3];
pByte[0] = pByte[0] ^ pByte[3];
// move lsb to msb
pByte[1] = pByte[1] ^ pByte[2];
pByte[2] = pByte[1] ^ pByte[2];
pByte[1] = pByte[1] ^ pByte[2];
#endif
}
And the usage is performed like so:
unsigned short int u16Val = 0x1234;
byte_swap16(&u16Val);
unsigned int u32Val = 0x12345678;
byte_swap32(&u32Val);
Below is an other approach that was useful for me
convertLittleEndianByteArrayToBigEndianByteArray (byte littlendianByte[], byte bigEndianByte[], int ArraySize){
int i =0;
for(i =0;i<ArraySize;i++){
bigEndianByte[i] = (littlendianByte[ArraySize-i-1] << 7 & 0x80) | (littlendianByte[ArraySize-i-1] << 5 & 0x40) |
(littlendianByte[ArraySize-i-1] << 3 & 0x20) | (littlendianByte[ArraySize-i-1] << 1 & 0x10) |
(littlendianByte[ArraySize-i-1] >>1 & 0x08) | (littlendianByte[ArraySize-i-1] >> 3 & 0x04) |
(littlendianByte[ArraySize-i-1] >>5 & 0x02) | (littlendianByte[ArraySize-i-1] >> 7 & 0x01) ;
}
}
Below program produce the result as needed:
#include <stdio.h>
unsigned int Little_To_Big_Endian(unsigned int num);
int main( )
{
int num = 0x11223344 ;
printf("\n Little_Endian = 0x%X\n",num);
printf("\n Big_Endian = 0x%X\n",Little_To_Big_Endian(num));
}
unsigned int Little_To_Big_Endian(unsigned int num)
{
return (((num >> 24) & 0x000000ff) | ((num >> 8) & 0x0000ff00) | ((num << 8) & 0x00ff0000) | ((num << 24) & 0xff000000));
}
And also below function can be used:
unsigned int Little_To_Big_Endian(unsigned int num)
{
return (((num & 0x000000ff) << 24) | ((num & 0x0000ff00) << 8 ) | ((num & 0x00ff0000) >> 8) | ((num & 0xff000000) >> 24 ));
}
#include<stdio.h>
int main(){
int var = 0X12345678;
var = ((0X000000FF & var)<<24)|
((0X0000FF00 & var)<<8) |
((0X00FF0000 & var)>>8) |
((0XFF000000 & var)>>24);
printf("%x",var);
}
Here is a little function I wrote that works pretty good, its probably not portable to every single machine or as fast a single cpu instruction, but should work for most. It can handle numbers up to 32 byte (256 bit) and works for both big and little endian swaps. The nicest part about this function is you can point it into a byte array coming off or going on the wire and swap the bytes inline before converting.
#include <stdio.h>
#include <string.h>
void byteSwap(char**,int);
int main() {
//32 bit
int test32 = 0x12345678;
printf("\n BigEndian = 0x%X\n",test32);
char* pTest32 = (char*) &test32;
//convert to little endian
byteSwap((char**)&pTest32, 4);
printf("\n LittleEndian = 0x%X\n", test32);
//64 bit
long int test64 = 0x1234567891234567LL;
printf("\n BigEndian = 0x%lx\n",test64);
char* pTest64 = (char*) &test64;
//convert to little endian
byteSwap((char**)&pTest64,8);
printf("\n LittleEndian = 0x%lx\n",test64);
//back to big endian
byteSwap((char**)&pTest64,8);
printf("\n BigEndian = 0x%lx\n",test64);
return 0;
}
void byteSwap(char** src,int size) {
int x = 0;
char b[32];
while(size-- >= 0) { b[x++] = (*src)[size]; };
memcpy(*src,&b,x);
}
output:
$gcc -o main *.c -lm
$main
BigEndian = 0x12345678
LittleEndian = 0x78563412
BigEndian = 0x1234567891234567
LittleEndian = 0x6745239178563412
BigEndian = 0x1234567891234567
I have char a[4] and in it:
a[0] = 0x76
a[1] = 0x58
a[2] = 0x02
a[3] = 0x00
And I want print it as int, can you tell me how to do that?
This works, but gives different results depending on the size of int, endian and so on..
#include <stdio.h>
int main(int argc, char *argv[])
{
char a[4];
a[0] = 0x76;
a[1] = 0x58;
a[2] = 0x02;
a[3] = 0x00;
printf("%d\n", *((int*)a));
return 0;
}
This is cleaner but you still have endian/size problems.
#include <stdio.h>
typedef union {
char c[4];
int i;
} raw_int;
int main(int argc, char *argv[])
{
raw_int i;
i.c[0] = 0x76;
i.c[1] = 0x58;
i.c[2] = 0x02;
i.c[3] = 0x00;
printf("%d\n", i.i);
return 0;
}
To force a certain endianness, build the int manually:
int i = (0x00 << 24) | (0x02 <<< 16) | (0x58 << 8) | (0x76);
printf("%d\n", i);
I think a union is the appropriate way to do this.
#include <stdio.h>
#include <stdint.h>
union char_int {
char chars[4];
int32_t num;
};
int main() {
union char_int tmp;
tmp.chars[0] = 0x76;
tmp.chars[1] = 0x58;
tmp.chars[2] = 0x02;
tmp.chars[3] = 0x00;
printf("%d\n", tmp.num);
}
Is the value stored in the array in big-endian or little-endian order? The portable way to do it is based on shift and mask, noting that in the general case, some of the high-order bits will be set and your plain char type might be signed or unsigned.
Little-endian
int i = (a[3] << 24) | ((a[2] & 0xFF) << 16) | ((a[1] & 0xFF) << 8) | (a[0] & 0xFF);
Big-endian
int i = (a[0] << 24) | ((a[1] & 0xFF) << 16) | ((a[2] & 0xFF) << 8) | (a[3] & 0xFF);
You can change those so that each term is consistently of the form ((a[n] & 0xFF) << m). If you know that plain char is unsigned, you can drop the mask operations. You can also use a cast: unsigned char *u = (unsigned char *)a; and then dereference u instead of a.
If you want to read it as a big- or little-endian integer, just do some bit shifting:
char a[4] = {0x76, 0x58, 0x02, 0x00};
// Big-endian:
uint32_t x = ((uint8_t)a[0] << 24) | ((uint8_t)a[1] << 16) | ((uint8_t)a[2] << 8) | (uint8_t)a[3];
// Little-endian:
uint32_t y = (uint8_t)a[0] | ((uint8_t)a[1] << 8) | ((uint8_t)a[2] << 16) | ((uint8_t)a[3] << 24);
If you want to read it as a native-endian integer, you can either cast the array to a pointer to an integer and dereference that. Note that the former is allowed only for char arrays -- for any other types, doing so breaks C's strict aliasing rules, so that would not be safe or portable. For example:
char a[4] = {0x76, 0x58, 0x02, 0x00};
// Cast to pointer to integer and dereference. This is only allowed if `a' is an
// array of `char'.
uint32_t x = *(uint32_t *)a;
Alternatively, you can use a union, or just memcpy() the data directly. Both of these are safe and portable, as long as a char is 8 bits (its size in bits is given by the macro CHAR_BIT).
char a[4] = {0x76, 0x58, 0x02, 0x00};
uint32_t x;
// Copy the data directly into x
memcpy(&x, a, sizeof(x));
// Use a union to perform the cast
union
{
char a[4];
uint32_t x;
} u;
memcpy(u.a, a, sizeof(a));
// u.x now contains the integer value
Note that I've used uint32_t in all of the examples above, since an int is not guaranteed to be 4 bytes on all systems. The type uint32_t is defined in the header file <stdint.h>, and if it's defined by your compiler, it's guaranteed to be 32 bits wide.
Other option can be using bitwise operators | and << left shift, as follows (to understand read comments):
int main(int argc, char *argv[])
{
char a[4];
int32_t i = 0; // 32 bits = 4 bytes
a[0] = 0x76;
a[1] = 0x58;
a[2] = 0x02;
a[3] = 0x00;
i = 0; // initial value must be `0`
i = i | a[0] << ( 3 * 8); // 0x76 => 0x76 00 00 00, gives i = 0x76 00 00 00
i = i | a[1] << ( 2 * 8); // 0x58 => 0x00 58 00 00, gives i = 0x76 58 00 00
i = i | a[2] << ( 1 * 8); // 0x02 => 0x00 00 02 00, gives i = 0x76 58 02 00
i = i | a[3] << ( 0 * 8); // 0x02 => 0x02
// => 0x00 00 00 02, gives i = 0x76 58 02 00
printf("Hex: %x\nDec: %d \n", i, i);
return 0;
}
ouput:
$ gcc -Wall -pedantic yy.c
$ ./a.out
Hex: 76580200 <- "hex decimal"
Dec: 1985479168 <- "decimal"
Notice: i = i | a[3] << ( 0 * 8); can be just i = i | a[3];, I written like that to keep code uniform.
Edit:
Oh you can just do it like:
i = 0 |
a[0] << ( 3 * 8) |
a[1] << ( 2 * 8) |
a[2] << ( 1 * 8) |
a[3] << ( 0 * 8);
Look here:Codepade for working code.
I have an array of four unsigned chars. I want to treat it like a 32-bit number (assume the upper bits of the char are don't care. I only care about the lower 8-bits). Then, I want to circularly shift it by an arbitrary number of places. I've got a few different shift sizes, all determined at compile-time.
E.g.
unsigned char a[4] = {0x81, 0x1, 0x1, 0x2};
circular_left_shift(a, 1);
/* a is now { 0x2, 0x2, 0x2, 0x5 } */
Edit: To everyone wondering why I didn't mention CHAR_BIT != 8, because this is standard C. I didn't specify a platform, so why are you assuming one?
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);
}
}
Obviously
While keeping in mind plain C the best way is
inline void circular_left_shift(char *chars, short shift) {
__int32 *dword = (__int32 *)chars;
*dword = (*dword << shift) | (*dword >> (32 - shift));
}
Uhmm, char is 16 bits long, was not clear for me. I presume int is still 32 bit.
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;
}
Or you could just unwind this cycle.
You could dig further into asm instruction ror, on x86 it's capable of performing such shift up to 31 bits left. Something like a
MOV CL, 31
ROR EAX, CL
Use union:
typedef union chr_int{
unsigned int i;
unsigned char c[4];
};
It's safer (because of pointer aliasing) and easier to manipulate.
EDIT: you should have mention earlier that your char isn't 8 bits. However, this should do the trick:
#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
};