byte array and long??

W

w3r3w0lf

hello!
I have a following situation:
I have a byte array where at a certain location are stored 4 bytes, and
these should be "put" into long variable (or any other 4 byte one).
ie:
byte a[]={0x0,0x0,0xfe,0x30,0x9e,0x2,0x66,0,0}
and the bytes 0xfe,0x30,0x9e,0x2 should be put into long variable which
should then contain 43921662
how to achieve this?

thanks!
 
J

John Harrison

w3r3w0lf said:
hello!
I have a following situation:
I have a byte array where at a certain location are stored 4 bytes, and
these should be "put" into long variable (or any other 4 byte one).
ie:
byte a[]={0x0,0x0,0xfe,0x30,0x9e,0x2,0x66,0,0}
and the bytes 0xfe,0x30,0x9e,0x2 should be put into long variable which
should then contain 43921662
how to achieve this?

thanks!

This *might* work,

long x = *reinterpret_cast<long*>(a + 2);

but if it doesn't it is because you have to swap the bytes around.

byte tmp[4] = { a[5], a[4], a[3], a[2] }; // swap bytes
long x = *reinterpret_cast<long*>(tmp);

john
 
J

Jack Klein

w3r3w0lf said:
hello!
I have a following situation:
I have a byte array where at a certain location are stored 4 bytes, and
these should be "put" into long variable (or any other 4 byte one).
ie:
byte a[]={0x0,0x0,0xfe,0x30,0x9e,0x2,0x66,0,0}
and the bytes 0xfe,0x30,0x9e,0x2 should be put into long variable which
should then contain 43921662
how to achieve this?

thanks!

This *might* work,

long x = *reinterpret_cast<long*>(a + 2);

but if it doesn't it is because you have to swap the bytes around.

byte tmp[4] = { a[5], a[4], a[3], a[2] }; // swap bytes
long x = *reinterpret_cast<long*>(tmp);

john

But it will fail on an ARM (and some other processors) with an
addressing fault due to improper alignment.

It will fail on a TI 320F28xx because the long will contain 0x003000fe
which is not what the OP asked for.

And in fact it is undefined behavior on any
platform/architecture/implementation.
 
R

rolo

w3r3w0lf said:
hello!
I have a following situation:
I have a byte array where at a certain location are stored 4 bytes, and
these should be "put" into long variable (or any other 4 byte one).
ie:
byte a[]={0x0,0x0,0xfe,0x30,0x9e,0x2,0x66,0,0}
and the bytes 0xfe,0x30,0x9e,0x2 should be put into long variable which
should then contain 43921662
how to achieve this?

thanks!

try this and tell me if this works!

#include <iostream>
using namespace std;

int main(){
char a[] = {0x0,0x0,0xfe,0x30,0x9e,0x2,0x66,0,0};
long b=0;

memcpy(&b,&a[2], sizeof(4));

cout << b << endl;
cin.get();
}



~ Let us linux ~
 
J

John Harrison

Jack Klein said:
w3r3w0lf said:
hello!
I have a following situation:
I have a byte array where at a certain location are stored 4 bytes, and
these should be "put" into long variable (or any other 4 byte one).
ie:
byte a[]={0x0,0x0,0xfe,0x30,0x9e,0x2,0x66,0,0}
and the bytes 0xfe,0x30,0x9e,0x2 should be put into long variable which
should then contain 43921662
how to achieve this?

thanks!

This *might* work,

long x = *reinterpret_cast<long*>(a + 2);

but if it doesn't it is because you have to swap the bytes around.

byte tmp[4] = { a[5], a[4], a[3], a[2] }; // swap bytes
long x = *reinterpret_cast<long*>(tmp);

john

But it will fail on an ARM (and some other processors) with an
addressing fault due to improper alignment.

It will fail on a TI 320F28xx because the long will contain 0x003000fe
which is not what the OP asked for.

And in fact it is undefined behavior on any
platform/architecture/implementation.

I never claimed my answer was platform independent. A truly platform
independent answer is surprisingly difficult. Perhaps you could oblige the
OP with such an answer?

John
 
M

Martijn Lievaart

hello!
I have a following situation:
I have a byte array where at a certain location are stored 4 bytes, and
these should be "put" into long variable (or any other 4 byte one).
ie:
byte a[]={0x0,0x0,0xfe,0x30,0x9e,0x2,0x66,0,0}
and the bytes 0xfe,0x30,0x9e,0x2 should be put into long variable which
should then contain 43921662
how to achieve this?

Assuming unsigned char for byte, this should work portably and safely:

long l = 0;

for (size_t ix=5; ix>1; ++ix) {
l <<= 8;
l |= a[ix];
}

If byte is signed, stick in a cast to unsigned char.

HTH,
M4
 
J

John Harrison

Martijn Lievaart said:
hello!
I have a following situation:
I have a byte array where at a certain location are stored 4 bytes, and
these should be "put" into long variable (or any other 4 byte one).
ie:
byte a[]={0x0,0x0,0xfe,0x30,0x9e,0x2,0x66,0,0}
and the bytes 0xfe,0x30,0x9e,0x2 should be put into long variable which
should then contain 43921662
how to achieve this?

Assuming unsigned char for byte, this should work portably and safely:

long l = 0;

for (size_t ix=5; ix>1; ++ix) {
l <<= 8;
l |= a[ix];
}

If byte is signed, stick in a cast to unsigned char.

HTH,
M4

Sorry to be pedantic, but it assumes 8 bits for char. Replace 8 with
CHAR_BIT from <limits.h>.

Also to be extremely pedantic I don't think that the standard gives any
guarantees and to the 'mathematical' behaviour of << when the left argument
is long (unsigned long would be different). So there is no guarantee that l
<<= 8 is the same as l *= 256. But if you were to replace l <<= 8 with l *=
256 then you would run into undefined behaviour because of the potential
overflow (again it would be different with unsigned long). At least that's
how I remember it, as usual I can't find the reference in the standard.

Sometimes it seems to me that the standard makes simple things very
difficult.

john
 
M

Martijn Lievaart

Assuming unsigned char for byte, this should work portably and safely:

long l = 0;

for (size_t ix=5; ix>1; ++ix) {
l <<= 8;
l |= a[ix];
}

If byte is signed, stick in a cast to unsigned char.

Sorry to be pedantic, but it assumes 8 bits for char. Replace 8 with
CHAR_BIT from <limits.h>.

Good point, but actually depends on the input. If the input is octets
(which is quite likely, most of the world talks octets, 8 is correct.
Also to be extremely pedantic I don't think that the standard gives any
guarantees and to the 'mathematical' behaviour of << when the left argument
is long (unsigned long would be different). So there is no guarantee that l
<<= 8 is the same as l *= 256. But if you were to replace l <<= 8 with l *=
256 then you would run into undefined behaviour because of the potential
overflow (again it would be different with unsigned long). At least that's
how I remember it, as usual I can't find the reference in the standard.

Right.

5.8 clause two. A left shift shifts left the bit pattern making up the
object. The reference to bitpattern makes it clear that this is
implementation defined for signed. It even explicitly states that it has
defined behaviour for unsigned integers.

5 clause 5. All overflows result in UB. So if the shift-left or the *256
results in a (signed) long that would be greater than LONG_MAX, we enter
UB.

3.9.1 clause 4. All unsigned integer types shall obey modulo-2 arithmetic.

3.9.1 clause 3. The bitpatterns for positive signed integers are the same
as their unsigned counterpart.

So left-shifting works only with unsigned long, and with signed long when
the input results in a positive number <= LONG_MAX. It is also guarenteed
to work with negative longs if you know for a fact that your machine uses
2's-complement arithmetic, which is a non-portable assumption.

Also, if the original bit pattern originated on the same machine, the
left-shift solution is required to work with signed long, however, in that
case this is musch simpler:

long l;
memcpy(&l, a+2, sizeof(long));

Multiplying with 256 works for unsigned long, and with signed long when
the input results in a positive number <= LONG_MAX. In practice it will
work with 2's-complement, but contrary to left-shifting the standard does
not guarentee that.

Another point to note, is that the standard probably only guarentees the
result if the type byte is an unsigned type. If the type byte is a signed
char for instance:

l |= a[ix];

would convert a[ix] to a signed long, hardly what you want.

l |= static_cast<unsigned char>(a[ix]);

Makes 4.7 clause 2 apply:

"2 If the destination type is unsigned, the resulting value is the least
unsigned integer congruent to the source integer (modulo 2n where n is the
number of bits used to represent the unsigned type). [Note: In a two s
complement representation, this conversion is conceptual and there is no
change in the bit pattern (if there is no truncation). ]"

Which I don't understand, but clearly implies the bit pattern can change
on non-2's-complement machines.
Sometimes it seems to me that the standard makes simple things very
difficult.

Yup. OTOH, this stuff /is/ difficult. Use text formats or network-order if
portability is an issue. If using network order, unly use it for unsigned
types.

M4
 
M

Martijn Lievaart

This *might* work,

long x = *reinterpret_cast<long*>(a + 2);

but if it doesn't it is because you have to swap the bytes around.

byte tmp[4] = { a[5], a[4], a[3], a[2] }; // swap bytes
long x = *reinterpret_cast<long*>(tmp);

john

But it will fail on an ARM (and some other processors) with an
addressing fault due to improper alignment.

It will fail on a TI 320F28xx because the long will contain 0x003000fe
which is not what the OP asked for.

And in fact it is undefined behavior on any
platform/architecture/implementation.

I never claimed my answer was platform independent. A truly platform

No, but you indicated that it could fail due to byte order, where it can
in fact crash.
independent answer is surprisingly difficult. Perhaps you could oblige the
OP with such an answer?

See the other subthread, where a better answer is discussed. To truly
answer the question, we should know more about the input and context.

HTH,
M4
 
R

Rob Williscroft

w3r3w0lf wrote in
hello!
I have a following situation:
I have a byte array where at a certain location are stored 4 bytes, and
these should be "put" into long variable (or any other 4 byte one).
ie:
byte a[]={0x0,0x0,0xfe,0x30,0x9e,0x2,0x66,0,0}
and the bytes 0xfe,0x30,0x9e,0x2 should be put into long variable which
should then contain 43921662
how to achieve this?

#include <iostream>
#include <limits>

typedef unsigned char byte;

byte a[]={0x0,0x0,0xfe,0x30,0x9e,0x2,0x66,0,0};
byte m[] = { 0xB2, 0x9E, 0x43, 0xFF }; /* -12345678 */

long four_bytes_to_long( byte const *bp )
{
unsigned long ul =
( bp[0] * 1UL ) +
( bp[1] * 256UL ) +
( bp[2] * 256UL * 256UL ) +
( bp[3] * 256UL * 256UL * 256UL )
;

unsigned long const lmax = std::numeric_limits< long >::max();

return ( ul > lmax ) ? -long(~ul + 1) : long( ul );
}

int main()
{
std::cerr << four_bytes_to_long( a + 2 ) << '\n';
std::cerr << four_bytes_to_long( m ) << '\n';
}

HTH.

Rob.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
474,160
Messages
2,570,889
Members
47,420
Latest member
ZitaVos505

Latest Threads

Top