Sign in to follow this  

C++ Convert array elemets

This topic is 3301 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

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;

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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?

Share this post


Link to post
Share on other sites
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];
}

Share this post


Link to post
Share on other sites
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];

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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).

Share this post


Link to post
Share on other sites
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]

Share this post


Link to post
Share on other sites

This topic is 3301 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this