1

I have to read 10 bytes from a file and the last 4 bytes are an unsigned integer. But I got a 11 char byte long char array / pointer. How do I convert the last 4 bytes (without the zero terminating character at the end) to an unsigned integer?

//pesudo code
char *p = readBytesFromFile();
unsigned int myInt = 0;
for( int i = 6; i < 10; i++ )
    myInt += (int)p[i];

Is that correct? Doesn't seem correct to me.

Davlog
  • 2,162
  • 8
  • 36
  • 60
  • 2
    Use `memcpy`. `*(int*)(p+6)` (1) can run into alignment problems and (2) violates strict aliasing. Endianness can also be an issue. – T.C. Oct 04 '14 at 19:30
  • 3
    You need to essentially shift the bits of the different bytes into the appropriate positions. Depending on the endianess of the transferred value. The assignment in the loop may be `myInt = myInt << 8 | static_cast(p[i])`. Alternatively you may want to loop through the loop in reverse. – Dietmar Kühl Oct 04 '14 at 19:30
  • 2
    Guys, those should all be made into answers, not comments. – Ben Oct 04 '14 at 19:35

4 Answers4

4

The following code might work:

myInt = *(reinterpret_cast<unsigned int*>(p + 6));

iff:

  • There are no alignment problems (e.g. on a GPU memory space this is very likely to blow if some guarantees aren't provided).
  • You can guarantee that the system endianness is the same used to store the data
  • You can be sure that sizeof(int) == 4, this is not guaranteed everywhere

If not, as Dietmar suggested, you should loop over your data (forward or reverse according to the endianness) and do something like

myInt = myInt << 8 | static_cast<unsigned char>(p[i])

this is alignment-safe (it should be on every system). Still pay attention to points 1 and 3.

Community
  • 1
  • 1
Marco A.
  • 43,032
  • 26
  • 132
  • 246
2

I agree with the previous answer but just wanna add that this solution may not work 100% if the file was created with a different endianness.

I do not want to confuse you with extra information but keep in mind that endianness may cause you problem when you cast directly from a file.

Here's a tutorial on endianness : http://www.codeproject.com/Articles/4804/Basic-concepts-on-Endianness

DomDom
  • 76
  • 5
1

Try myInt = *(reinterpret_cast<unsigned int*>(p + 6));.

This takes the address of the 6th character, reinterprets as a pointer to an unsigned int, and then returns the (unsigned int) value it points to.

Louis Newstrom
  • 172
  • 1
  • 1
  • 13
  • This might be dangerous with regard to endianness – Marco A. Oct 04 '14 at 20:13
  • Because there is no `unsigned int` variable to look at. We are looking at arbitrary memory, which requires a pointer. `reinterpret_cast` only works on pointers for that reason. – Louis Newstrom Oct 05 '14 at 13:03
0

Maybe using an union is an option? I think this might work; UPDATE: Yes, it works.

union intc32 {
    char c[4];

    int v;
};

int charsToInt(char a, char b, char c, char d) {
    intc32 r = { { a, b, c, d } };
    return r.v;
}
Orbyfied
  • 94
  • 11