11

I have a 32 bit long variable, CurrentPosition, that I want to split up into 4, 8bit characters. How would I do that most efficiently in C? I am working with an 8bit MCU, 8051 architectecture.

unsigned long CurrentPosition = 7654321;
unsigned char CP1 = 0;
unsigned char CP2 = 0;
unsigned char CP3 = 0;
unsigned char CP4 = 0;
// What do I do next? 

Should I just reference the starting address of CurrentPosition with a pointer and then add 8 two that address four times?

It is little Endian.

ALSO I want CurrentPosition to remain unchanged.

skaffman
  • 398,947
  • 96
  • 818
  • 769
PICyourBrain
  • 9,976
  • 26
  • 91
  • 136

6 Answers6

24
    CP1 = (CurrentPosition & 0xff000000UL) >> 24;
    CP2 = (CurrentPosition & 0x00ff0000UL) >> 16;
    CP3 = (CurrentPosition & 0x0000ff00UL) >>  8;
    CP4 = (CurrentPosition & 0x000000ffUL)      ;

You could access the bytes through a pointer as well,

unsigned char *p = (unsigned char*)&CurrentPosition;
//use p[0],p[1],p[2],p[3] to access the bytes.
nos
  • 223,662
  • 58
  • 417
  • 506
7

I think you should consider using a union:

union {
   unsigned long position;
   unsigned char bytes[4];
} CurrentPosition;

CurrentPosition.position = 7654321;

The bytes can now be accessed as: CurrentPosition.bytes[0], ..., CurrentPosition.bytes[3]

Justin Muller
  • 1,283
  • 13
  • 21
  • A good idea in practice because the compiler can do the decomposition of the int into bytes. A bad idea in theory because this usage of unions is undefined by the c-standard.. (most if not all implementations will just work though) – Nils Pipenbrinck Apr 30 '10 at 20:55
  • 1
    @Nils Type punning with unions has been well defined since C99. Code is still endian dependent though. – user694733 Jan 05 '18 at 10:11
2

If You are using an 8 bit MCU shifting a whole 32 bit variable is a bit of work. In this case it's better to read 4 bytes of CurrentPosition using pointer arithmetic. The cast:

unsigned char *p = (unsigned char*)&CurrentPosition;

doesn't change the CurrentPosition, but if You try to write to p[0] You will change the least significant byte of the CurrentPosition. If You want a copy do this:

unsigned char *p = (unsigned char*)&CurrentPosition;
unsigned char arr[4];
arr[0] = p[0];
arr[1] = p[1];
arr[2] = p[2];
arr[3] = p[3];

and work with arr. (If you want most significant byte first change the order in those assignments).

If You prefer 4 variables You can obviously do:

unsigned char CP1 = p[0];
unsigned char CP2 = p[1];
unsigned char CP3 = p[2];
unsigned char CP4 = p[3];
Maciej Hehl
  • 7,895
  • 1
  • 22
  • 23
0
CP1 = (unsigned char)(CurrentPosition & 0xFF);
CurrentPosition >>= 8;
CP2 = (unsigned char)(CurrentPosition & 0xFF);
...
Matt Greer
  • 60,826
  • 17
  • 123
  • 123
  • This would change the value in CurrentPosition right? I want to leave CurrentPosition unchanged. – PICyourBrain Apr 30 '10 at 19:50
  • Yes it would, one option is to make a copy of CurrentPosition and mangle the copy. Or nos's answer is another option. Your idea of using a pointer is also possible. There's many ways to do this. – Matt Greer Apr 30 '10 at 19:52
0
unsigned char *CP = &CurrentPosition;

Now CPn per your original code is accessed via CP[n].

Matt Joiner
  • 112,946
  • 110
  • 377
  • 526
0

I know this was posted some time ago. But for anyone still reading the thread: Many people take the approach of sequentially shifting the original value. Why not let the compiler do the work for you. Use a union & to allow you to store the values in the same location. Define a union consisting of both a 32 bit long variable (this will be where you save your CurrentPosition) and a structure consisting of 4 char variables. Or just a simple 8 bit integer array. When you write your CurrentPosition to the long variable, it will be stored in the same location accessed when you read the 4 char variables. This method is much less labour intensive and does not allows the compiler to do the work instead of wasting time & resources.

Sean
  • 1
  • 1
    That is exactly what [the second most upvoted answer](https://stackoverflow.com/a/2747324/2564301) suggests. – Jongware Jan 05 '18 at 09:56