0

I took this example from the following page. I am trying to convert long into a 4 byte array. This is the original code from the page.

long n;
byte buf[4];
buf[0] = (byte) n;
buf[1] = (byte) n >> 8;
buf[2] = (byte) n >> 16;
buf[3] = (byte) n >> 24;
long value = (unsigned long)(buf[4] << 24) | (buf[3] << 16) | (buf[2] << 8) | buf[1];

I modified the code replacing

long value = (unsigned long)(buf[4] << 24) | (buf[3] << 16) | (buf[2] << 8) | buf[1];

for

long value = (unsigned long)(buf[3] << 24) | (buf[2] << 16) | (buf[1] << 8) | buf[0];

I tried the original code where n is 15000 and value would return 0. After modifiying the line in question (i think there was an error in the indexes on the original post?) value returns 152.

The objetive is to have value return the same number as n. Also, n can be negative, so value should also return the same negative number.

Not sure what I am doing wrong. Thanks!

hcheung
  • 3,377
  • 3
  • 11
  • 23
acanessa
  • 125
  • 1
  • 12
  • 'byte' is not a standard C type. If it is signed, I think all bets are off with these bit manipulations. You're correct that the indices were incorrect though. Also, what is this meant to do: long value = (unsigned long) ... – pmacfarlane Nov 23 '22 at 23:15
  • 1
    Well, for starters there is *no* `buf[4]`, that's an off-by-1 bug. Arrays are always indexed 0 -> length-1. – Kingsley Nov 23 '22 at 23:15
  • 2
    If you replace 'long' with 'uint32_t' and 'byte' with 'uint8_t' then this will probably work. You'll need to #include – pmacfarlane Nov 23 '22 at 23:21
  • @pmacfarlane before commenting read the question (carefully) – 0___________ Nov 23 '22 at 23:49
  • 1
    Thank you @Kingsley. I didn't noticed that was wrong too in the original code. I changed it to buf[3] and removed (byte) casting. Also removed (unsigned long). Now it works por positive and negative numbers, up to 32767. I believe that is the max positive value for an integer, but n being declared as long, shouldn't it allow for bigger values? – acanessa Nov 23 '22 at 23:53
  • 1
    Can you just use a union to achieve this? – JohnScott Nov 23 '22 at 23:57

1 Answers1

0

You were correct that the indices were wrong. A 4-byte array indexes from 0 to 3, not 1 to 4.

The rest of the issues were because you were using a signed 'long' type. Doing bit-manipulations on signed datatypes is not well defined, since it assumes something about how signed integers are stored (twos-complement on most systems, although I don't think any standard requires it).

e.g. see here

You're then assigning between signed 'longs' and unsigned 'bytes'.

Someone else has posted an answer (possibly abusing casts) that I'm sure works. But without any explanation I feel it doesn't help much.

pmacfarlane
  • 3,057
  • 1
  • 7
  • 24