2

I am reading in binary data from a file:

char* buffIn = new char[8];
ifstream inFile(path, ifstream::binary);
inFile.read(buffIn, 8);

I then want to convert the char* read in (as binary) to an unsigned long but I am having problems - I am not quite sure what is going on, but for instance 0x00000000000ACD gets interpreted as 0xFFFFFFFFFFFFCD - I suspect all the 0x00 bytes are causing some sort of problem when converting from char* to unsigned long...

unsigned long number = *(buffIn);

How do I do this properly?

adrianmcmenamin
  • 1,081
  • 1
  • 15
  • 44

3 Answers3

5

Since buffIn is of type char pointer, when you do *(buffIn) you are just grabbing one character. You have to reinterpret the memory address as an unsigned long pointer and then dereference it.

unsigned long number = *((unsigned long*)buffIn);
imreal
  • 10,178
  • 2
  • 32
  • 48
  • This according to the standards will be undefined behavior. char pointer need not have to be aligned to integer boundary. – Sundar Feb 26 '14 at 00:27
  • Yes, I suppose that is obvious when you think about it. Thanks, will accept when I can. – adrianmcmenamin Feb 26 '14 at 00:31
  • @Sundar, it is aligned when pointing to allocated memory. Guaranteed by the standard. If the allocated memory is greater than `unsigned long`of course. – imreal Feb 26 '14 at 00:32
  • @Nick start of the allocated memory (using malloc/calloc) is always aligned to the max possible pointer boundary (perhaps long long), but not the memory not allocated by malloc/calloc. https://www.securecoding.cert.org/confluence/display/seccode/EXP36-C.+Do+not+convert+pointers+into+more+strictly+aligned+pointer+types – Sundar Feb 26 '14 at 00:35
  • @Sundar, from the standard: `1 Effects: The allocation function (3.7.3.1) called by a new-expression (5.3.4) to allocate size bytes of storage suitably aligned to represent any object of that size.` – imreal Feb 26 '14 at 00:37
  • @Nick, doesn't that mean `new char, will allocate pointer suitably aligned to represent any object of char size`?? – Sundar Feb 26 '14 at 00:39
  • @Sundar, you're right, the quote I wrote is for `new` only, but this one applies for `new []`, `1 Effects: The allocation function (3.7.3.1) called by the array form of a new-expression (5.3.4) to allocate size bytes of storage suitably aligned to represent any array object of that size or smaller.222)` – imreal Feb 26 '14 at 00:42
  • @Nick, I found http://stackoverflow.com/questions/506518/is-there-any-guarantee-of-alignment-of-address-return-by-cs-new-operation, look at the comments from BenVoigt – Sundar Feb 26 '14 at 00:47
  • let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/48424/discussion-between-sundar-and-nick) – Sundar Feb 26 '14 at 00:50
0

In addition to recasting the char[8] (which will only read the the first unsigned long - which is 32-bits in length), you can also use some simple bit-wise operations

unsigned long value = (((unsigned long)buffin[0]) << 24) | (((unsigned long)buffin[1]) << 16) | (((unsigned long)buffin[2]) << 8) | (unsigned long)buffin[3];
Zac Howland
  • 15,777
  • 1
  • 26
  • 42
0

Try something like

unsigned long* buffInL = new unsigned long[2];
char* buffIn=(char*)buffInL;
ifstream inFile(path, ifstream::binary);
inFile.read(buffIn, 8);

Unlike other types, char* is allowed to alias.

KitsuneYMG
  • 12,753
  • 4
  • 37
  • 58