Skip to main content
gamedev.net
🔒 Locked

C++ Convert array elemets

Started by REspawn 13 replies 1.3k views
Original Post
REspawn
REspawn
Hi, I have a UINT8 array of fixed size, how can I convert the four elements of the array to an int? Thanks
CodaKiller
CodaKiller
Quote:
Original post by REspawn
Hi,
I have a UINT8 array of fixed size, how can I convert the four elements of the array to an int?

Thanks


If you have 4 then that would be a long or DWORD since there are only 2 bytes in a int but the answer to your question is simple casting, like so:

int newint = (int)YourUINT8Array;
Remember Codeka is my alternate account, just remember that!
REspawn
REspawn
sorry if that was unclear, its an array with 20 UINT8's, how would I go about casting the first 4 to an int, then the next 4 to another and so on.
Driv3MeFar
Driv3MeFar
Quote:
Original post by CodaKiller
If you have 4 then that would be a long or DWORD since there are only 2 bytes in a int


What?
frob
frob
Note that an int is not guaranteed to hold 32 bits; it is guaranteed to hold at least 16. Most compilers have 32-bit ints, but it is not guaranteed by the language.

To do it portably you can just add and shift.

unsigned long result = a[0] << 24 + a[1] << 16 + a[2] << 8 + a[3];


There are many tricks for particular architectures and hardware such as casting the bytes directly into an int, but they rely on either implementation defined behavior or officially undefined behavior, so you should avoid them.
Antheus
Antheus
Quote:
Original post by CodaKiller

If you have 4 then that would be a long or DWORD since there are only 2 bytes in a int but the answer to your question is simple casting, like so:

int newint = (int)YourUINT8Array;


Int is commonly 32 bits these days. Variations exist depending on language and other factors.

The actual conversion depends on what UINT8 is. For example, under Winapi, BOOL is an int.
frob
frob
Quote:
Original post by CodaKiller
the answer to your question is simple casting, like so:

int newint = (int)YourUINT8Array;

Very incorrect. Even if you used (int)YourUINT8Array[0] it is still wrong.

* The UINT8 array may not be properly aligned for an int, which gives undefined behavior.
* A 16-bit int will give incorrect results since you only get two UINT8.
* A 64-bit int will give incorrect results since you get eight UINT8.
* Any size other than 32-bit int will give incorrect results.
* Big endian and little endian machines would give different and incorrect results.
* A byte is not guaranteed to be exactly 8 bits. Many chips use 9, 16, 32, or 36 bit bytes, so a "simple" cast on any one of those would undefined results.


The correct and portable way is to do this through bit shifting into an unsigned long which is guaranteed to hold at least 32 bits, as in my earlier post.
REspawn
REspawn
is memcpy ok / safe to use in a situation like this?

this works just fine...
int valueTwo = 0;
memcpy_s((void*)&valueTwo, 4, (void*)&rawHeader[4], 4);
frob
frob
Quote:
Original post by REspawn
is memcpy ok / safe to use in a situation like this?

this works just fine...
int valueTwo = 0;
memcpy_s((void*)&valueTwo, 4, (void*)&rawHeader[4], 4);

Depends on the byte ordering of your machine.

Your array value {0x0A, 0x0B, 0x0C, 0x0D} could become 0x0A0B0C0D or 0x0D0C0B0A. If the machine has 16-bit accessing it could even become 0x0C0D0A0B.

Perform bit shifts to be safe.

Of course, if you are saying to yourself, "I am writing for 32-bit Windows and I don't care if I write incorrect or even illegal C++ code", then you can ignore the advice and use the simple, fast, and unsafe cast.
REspawn
REspawn
Quote:
Original post by frob
Depends on the byte ordering of your machine.

Your array value {0x0A, 0x0B, 0x0C, 0x0D} could become 0x0A0B0C0D or 0x0D0C0B0A. If the machine has 16-bit accessing it could even become 0x0C0D0A0B.

Perform bit shifts to be safe.


I tried the bit shifts with the end result always being 0.

unsigned long result = rawHeader[4] << 24 + rawHeader[5] << 16 + rawHeader[6] << 8 + rawHeader[7];

this should now hold the number 3, any ideas what I'm doing wrong?
swiftcoder
swiftcoder
Quote:
Original post by REspawn
I tried the bit shifts with the end result always being 0.

unsigned long result = rawHeader[4] << 24 + rawHeader[5] << 16 + rawHeader[6] << 8 + rawHeader[7];

this should now hold the number 3, any ideas what I'm doing wrong?
You are shifting 8-bit numbers: what happens when you shift an 8-bit number 24-bits to the left? You get 0, since all existing bits are shifted out, and 0 bits are brought in from the right.

You also appear to be doing a byte-order conversion at the same time.

Try something like this:
unsigned long result = 0;for (int i = 4; i > 0; i++) {	result <<= 8;	result += rawHeader[i-1];}
Tristam MacDonald. Ex-BigTech Software Engineer. Future farmer. [https://trist.am]
DevFred
DevFred
Quote:
Original post by swiftcoder
You are shifting 8-bit numbers

No. The general rule is that everything smaller than an int is promoted to an int before the actual operation.
int main(void){    unsigned char b = 123;    printf("%d\n%d\n", sizeof b, sizeof (b+b));    return 0;}

This prints 1 for sizeof b and 4 for sizeof (b+b).
Quote:
Original post by REspawn
unsigned long result = rawHeader[4] << 24 + rawHeader[5] << 16 + rawHeader[6] << 8 + rawHeader[7];

+ has higher precedence than <<. Use | instead of +, that should work.

unsigned long result = rawHeader[4] << 24 | rawHeader[5] << 16 | rawHeader[6] << 8 | rawHeader[7];
swiftcoder
swiftcoder
Quote:
Original post by DevFred
Quote:
Original post by swiftcoder
You are shifting 8-bit numbers

No. The general rule is that everything smaller than an int is promoted to an int before the actual operation.
int main(void){    unsigned char b = 123;    printf("%d\n%d\n", sizeof b, sizeof (b+b));    return 0;}

This prints 1 for sizeof b and 4 for sizeof (b+b).
Ah shoot, forgot about integer promotion - thanks for correcting.
Tristam MacDonald. Ex-BigTech Software Engineer. Future farmer. [https://trist.am]
DevFred
DevFred
Yes, but the most important part is that due to operator precedence rules, the forumla with the + operator is evaluated as follows:
unsigned long result = rawHeader[4] << (24 + rawHeader[5]) << (16 + rawHeader[6]) << (8 + rawHeader[7]);

Which just shifts the bits from rawHeader[4] waaaaay too far to the left (at least 24 + 16 + 8 = 48 bits).
noe
noe
the simplest way (just reinterpreting memory block) would be:

int* intBegin = (Int*) uint8Array;
int* intEnd = intBegin + sizeOfUint8Array / sizeof(int);

std::copy(intBegin, intEnd, intArray);

[Edited by - noe on December 4, 2008 10:23:39 AM]

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.