Continue to Site

Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronics Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

How to shift bytes in C language?

Status
Not open for further replies.

tom12sg

Member level 2
Joined
Feb 1, 2004
Messages
45
Helped
4
Reputation
8
Reaction score
4
Trophy points
1,288
Activity points
422
Hi,

Sorry, if this is very fundamental. I just can't figure out...

I wish to shift a bytes to the left of a continuous 3 bytes, so I try this:
I'm not caring about little-ending of big-ending at this monent.

struct{
unsigned char val_hi;
unsigned char val_mid;
unsigned char val_lo;
}mix;

void shift_byte(unsigned char val)
{
mix.val_mid<<=8; //expect last value to move to hi
mix.val_lo <<=8; //expect last value to move to mid
mix.val_lo = val; //insert new value
}

main()
{

shift_byte(0x24);
shift_byte(0x79);
shift_byte(0x03);

//Wanted expected output: val_hi=0x24
// val_mid=0x79
// val_lo=0x03
}

How should the shifting be accompanish??
Please help. Thanks.
 

xgoat

Hi,

I would do it like this :

void shift_byte(unsigned char val)
{
mix.val_hi = mix.val_mid; //expect last value to move to hi
mix.val_mid = mix.val_lo; //expect last value to move to mid
mix.val_lo = val; //insert new value
}
 

c language union imagecraft

If you have a three byte array in the struct instead of the separate unsigned chars then you'll use less memory. This is because the compiler will align the unsigned chars in the struct to 2 byte boundaries. It also makes it more convinient if you want to increase the number of entries in your thing.
 

Re: Shift in C language

tom12sg said:
Hi,

struct{
unsigned char val_hi;
unsigned char val_mid;
unsigned char val_lo;
}mix;

main()
{

shift_byte(0x24);
shift_byte(0x79);
shift_byte(0x03);

//Wanted expected output: val_hi=0x24
// val_mid=0x79
// val_lo=0x03
}

How should the shifting be accompanish??
Please help. Thanks.

You can also try to make it a union between a 4-byte longword and the array of bytes.

union {
unsigned int quad;
struct{
unsigned char val_hi;
unsigned char val_mid;
unsigned char val_lo;
}mix;
} data;

Then you can try and do

data.quad = data.quad<<8 | new_data;

and use data.mix.val_hi to access individual members. This is dependent of endianness and padding bytes (3 to 4 bytes) so you may need to rearrange the struct contents a bit (perhaps add a dummy and take endianness into account).

The advantage is that it uses a 32-bit shift operation to do everything in one go.

The same union effect can also be achieved using pointers of type char* and int*, pointing to the same memory location (the struct).
 

Re: Shift in C language

vomit's technique is nice and looks better then casting your struct to another type of pointer! Essentially it does the same but in this way it looks more elegant.
But you should check the size of an int for your compiler!!! for example: Imagecraft for AVR uses 16-bit for an int! a long is 32 bit.

It's better (for porting to other compilers/architectures) to define your own types!

for example:
Code:
typedef unsigned char  u8;
typedef signed char    s8;
typedef unsigned short u16;
typedef signed short   s16;
typedef unsigned long  u32;
typedef signed long    s32;
 

Re: Shift in C language

There's a group of types with names of the form intN_t, where N is the number of bits required for an integer. The legal values of N are 8, 16, 32 and 64. Some compilers implement 24. It's highly advisable to use these types if you want a specific size of variable.

The union method is somewhat nasty, as it assumes that the compiler stores the values in memory in a particular way. Unions weren't really invented for writing as one type and reading back as another. They were primarily created for databasing applications where different types of variable could be stored in a field. Stay away from unions!

Also, the previously mentioned union method is likely not to function correctly, as the integers within the stuct "mix" may be aligned to 2 byte boundaries.
 

Re: Shift in C language

so if all of the above isn't correct then can you give us a solution for this problem ? 8)

bye

Fire in the Wire :sm2:



[/quote]
 

Re: Shift in C language

Yes. (note that i've used the uintN_t group - similar to intN_t, but unsigned). If you want it in a struct then put the array in a struct...

Note: Some of the previously mentioned examples may actually work in some compilers, but not necessarily in most. This one should work in most compilers.


Code:
#include <stdint.h>

uint8_t  thing[3];

void shift_byte( uint8_t val )
{
 thing[2] = thing[1];
 thing[1] = thing[0];
 thing[0] = val;
}

int main( void )
{

 shift_byte(0x24);
 shift_byte(0x79);
 shift_byte(0x03); 

 return 0;
}
 

Re: Shift in C language

I agree with xgoat,
When you only need byteshifts, the shift_byte method seems to be the best. It will work on most architectures and with most compilers.
Other solutions, using bitshifts might cause problems due to byte placement. There might be differences between placement of the bytes in array's, in structs and in integers. You should verify whether your compiler/architecture does this in a consistent way before using any of the other techniquest.
Perhaps there can be a slight performance gain with other techniques (eg, when your uC supports a 32 byte shift) but is it worth the trouble (and perhaps your compiler will do the optimization for you).
 

Status
Not open for further replies.

Similar threads

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top