j_mcnally
j_mcnally

Reputation: 6958

Casting a char array to an integer

Basically I am reading a binary format where 4 bytes specify the size of the string to follow. So i want to cast 4 chars I am reading from a buffer to 1 integer.

Here is what I have.

int FileReader::getObjectSizeForMarker(int cursor, int eof, char * buffer) {
  //skip the marker and read next 4 byes
  int cursor = cursor + 4; //skip marker and read 4
  char tmpbuffer[4] = {buffer[cursor], buffer[cursor+1], buffer[cursor+2], buffer[cursor+3]};
  int32_t objSize = tmpbuffer;
  return objSize;

}

thoughts?

Upvotes: 2

Views: 4200

Answers (5)

Mark Tolonen
Mark Tolonen

Reputation: 177406

You can use the ntohl function to convert from network to host byte-order. No need to reinvent the wheel. This also has the advantage of being somewhat portable and will work on big-endian and little-endian OSes as long as the correct headers are used. Below is a Windows example, but the function is available on Linux as well:

#include <winsock.h>
#include <iostream>

int main()
{
    char buffer[] = "MARK\x00\x00\x00\x08";
    // Point to the 4-byte network (big-endian) order value.
    unsigned long * size = (unsigned long *)(buffer + 4);
    // Dereference and convert it.
    std::cout << ntohl(*size) << std::endl;
    return 0;
}

Output:

8

Upvotes: -1

WhozCraig
WhozCraig

Reputation: 66194

assuming these are stored MSB (i.e. big endian).

unsigned char *p = (unsigned char*)buffer + cursor;
uint32_t uiSize = (unsigned int)*p <<24 |
                  (unsigned int)*(p+1) << 16 |
                  (unsigned int)*(p+2) << 8 |
                  (unsigned int)*(p+3);

Cast the result to a signed int after assembly. Hideous I know, but so are my typing skills.

Note:I honestly can't remember if the implicit up-cast extends the sign from a char to an int or not but if it does, and any of the single bytes being or'd together here are top-bit-lit, you may be in for a surprise if *p was not. Thus the seemingly paranoid unsigned cast-o-festival, and the followup to cast to signed-int only after full assembled.

Upvotes: 4

nneonneo
nneonneo

Reputation: 179392

It's pretty easy to do the unpacking manually:

unsigned char *ptr = (unsigned char *)(buffer + cursor);
// unpack big-endian order
int32_t objSize = (ptr[0] << 24) | (ptr[1] << 16) | (ptr[2] << 8) | ptr[3];

Upvotes: 5

Sidharth Mudgal
Sidharth Mudgal

Reputation: 4264

This should do the trick:

objSize = 0;
for (int i = 0; i < 4; ++ i)
    objeSize += ((int)tmpbuffer[i]) << (8 * i);

OR

objSize = 0;
for (int i = 0; i < 4; ++ i)
    objeSize += ((int)tmpbuffer[i]) << (8 * (3 - i));

for big endian as nneonneo pointed out

Upvotes: 2

imreal
imreal

Reputation: 10348

What you have should work fine but replace this

int32_t objSize = tmpbuffer;

for this

int32_t objSize = *((int32_t*)tmpbuffer);
  • It must be stored and read in the same architecture.

Upvotes: -1

Related Questions