Reputation: 6958
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
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
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
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
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
Reputation: 10348
What you have should work fine but replace this
int32_t objSize = tmpbuffer;
for this
int32_t objSize = *((int32_t*)tmpbuffer);
Upvotes: -1