How best to build a Unit8_t array from an int value

I am trying to convert an int variable for example 1325 which = 52D in Hex into a unit 8 array in the following format

byte Array[5] = {0x00, 0x50, 0x02, 0x0D, };

This is angular position information for a Pan Tilt head which I need to send back. Seems simple but its driving me nuts! if it looks simple enough to you any help would be appreciated.

int x = 1325;
uint8_t Array[5]={0};
for (uint8_t i=5;i>0;i--){
  Array[i-1]=x%16;
  x=(x-Array[i-1])/16;
}

Showing complete code of what you're trying to do helps other people help you.

First: are you SURE that's the requirement? Splitting it by nybbles instead of bytes is very strange and it's strange that Array[1] is 0x50 instead of 0x5 even if that IS what you want. =

Are you sure that the requirement isn't instead that
uint8_t Array[4] = { 0, 0, 5, 0x2d } ? That would be 5*256 +2*16 + 13 = 1325.

If it's the latter, and you have int num = 1325 and you want to see it as an array of bytes, just set uint8_t*foo = &num, taking the address of your original number and making a uint8_t pointer from that, and then iterate the array from 3 to 0 and you'll get the component bytes:

➜  /tmp cat m.c
#include <stdio.h>
#include <stdint.h>

int main(void) {
 int num = 1325;
 uint8_t* foo = (uint8_t*) &num;
 for (int i = 3; i >= 0; i--) {
	 printf("%02x ", foo[i]);
 }
 printf("\n");
 return 0;
}
➜  /tmp make m && ./m
cc     m.c   -o m
00 00 05 2d

Now if you really DID mean to bust it into nybbles AND there is a typo in your 0x50 (see why accuracy in a question matters? Us GUESSING the question to give you answers is risky to confuse you and makes busy work for us and the readers) then you'll have to shift it out a nybble at a time, mask it, and store it.

Here we loop backward and for each nybble we mask those four bits (0xf) by masking with (e.g. for the second iteration) 0x0f << 2*4 to get that 0x500 and then shift right by 2*4 to move it right eight bits to get that '5' into the bottom nybble. The program looks like:

➜  /tmp cat m2.c
#include <stdio.h>
#include <stdint.h>

int main(void) {
 int num = 1325;
 uint8_t array[4];
 for (int i = 3; i >= 0; i--) {
   array[3-i] = (num  & 0xf << (i*4)) >> i*4;
 }
 for (int i = 0 ; i < 4; i++) {
   printf("%02x ", array[i]);
 }
 printf("\n");
 return 0;
}
➜  /tmp make m2 && ./m2
cc     m2.c   -o m2
00 05 02 0d

...but I'll reiterate that this is super weird. Maybe your sensor is returning things in nybbles and you need to break them apart (never underestimate how strange hardware registers can be) but breaking it into the compopnent bytes (my first example) is a much more common/normal thing to do.

July 17 Edit: Replace * with \* in case anyone actually reads the prose.

The correct way is to use memcpy().

1 Like

consider
output

 x: 1325, 0x52D
 D 2 5 0
uint8_t array [4];

void
setup ()
{
    Serial.begin (9600);

    int x = 1325;
    Serial.print   (" x: ");
    Serial.print   (x);
    Serial.print   (", 0x");
    Serial.println (x, HEX);

    for (unsigned i = 0; i < (2*sizeof(x)); i++)  {
        array [i] = x & 0xF;
        x       >>= 4;
    }

    for (unsigned i = 0; i < sizeof(array); i++)  {
        Serial.print (" ");
        Serial.print (array [i], HEX);
    }
    Serial.println ();
}

void
loop (void) {
}

what happens when 1== 1?

1 Like

Thanks for your time.
The 0x50 was a typo. The Strange format is all down to Sony VISA protocol which breaks everything down this way.

Needs a few tweaks. The starting offset is wrong and the iterator has to be signed in order to terminate the loop as this version will run forever. This version takes their algorithm into my framework and corrects those issues.

➜  /tmp cat m3.c

#include <stdio.h>
#include <stdint.h>

int main(void) {
 int x = 1325;
 uint8_t array[5] ;

 for (int8_t i=5;i>0;i--){
  array[i-2]=x%16;
  x=(x-array[i-2])/16;
 }

 for (int i = 0 ; i < 4; i++) {
   printf("%02x ", array[i]);
 }
 printf("\n");
 return 0;
}
➜  /tmp make m3 && ./m3
make: `m3' is up to date.
00 05 02 0d

Note this version munches the bits that have been consumed with division and modulo where mine used bitmasks. Since this is embedded land and you didn't state what CPU or build environment you were using, we don't know if adding division and modulo will require floating point or a floating point emulation to be dragged in to do this math.

This bit twiddling is cleaner than mine, but in order to nail the order requirement, I suspect that array[i] = x & 0xf should be something like array[3-i] = x & 0x0f, shouldn't it?

You need the first pass into element 3, the second pass into element 2, and so on.

Undefined behaviour. That's probably why it was crashing, which I papered over with the unsigned thing. Array[-1] is probably in the memory holding 'x' in my example, so that was resetting the loop iterator which probably caused the infinite loop in my code. Your analysis is right and my "fix" was wrong. But I think we've presented several different "better" ways by now.

Many Thanks for your help this does exactly what I'm looking for with very few lines of code.

you seen even me got not immediately what i want to write.

In order to improve your answer:
In normal text, * is not printed....
One workaround is to add code tags.

1 Like

Thank you for the tip, @build_1971 . Learning every BBS/Forum software and their requirements is kind of a drag. (This was my first post here.) Turns out that just replacing * with \** in the prose worked well with low overhead.

The posts weren't even voted helpful, nor was it closed, so I got no notication. I wasn't sure if anyone even read them or not until I was scanning the group and saw my own answers here.

Code on!

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.