4

I have a file that I read into a char array.

The char array now holds a certain number of bytes, now if I know the file stored a 32bit integer in little endian at position say 0x8, how do I retrieve it from the char array?

FILE * file = fopen("file");
char buffer[size];
fread(buffer,1,size,file);
int = buffer[0x8]; // What should I do here?
// I imagine it involves some strange pointer
// arithmetic but I can't see what I should do,
// casting to int just takes the first byte,
// casting to (int *) doesn't compile
J V
  • 11,402
  • 10
  • 52
  • 72

4 Answers4

4

The "easy" way, assuming the array contains a byte of the same endianness as your machine, and that there aren't any special alignment requirements, is:

int x = *(int *)&buffer[8];

If you do have an endianness difference, you'll need to handle that. If there's an alignment problem (or even potentially an alignment problem), you should extract the bytes one by one:

int x = buffer[8] + (buffer[9] << 8) + (buffer[10] <<  16) + (buffer[11] << 24);

Or possibly the other direction if the endianness is the other way.

Carl Norum
  • 219,201
  • 40
  • 422
  • 469
  • 1
    +1. I just want to add that `*((int*)(buffer + 8))` would be the same. It is most likely that you have **little-endian** machine - Intel or AMD... – LihO Feb 06 '12 at 19:17
3

you need to cast it like so:

int foo = *((int *) &buffer[0x8]);

Which will first cast the spot to a int pointer and the dereference it to the int itself.

[watch out for byte-ordering across different machine types though; some do high bytes first some do low]

And just to make sure the example is well understood, here's some code showing the results:

#include <stdio.h>

main() {
    char buffer[14] = { 0,1,2,3,4,5,6,7,8,9,10,11,12,13 };
    int foo = *((int *) &buffer[0x8]);
    int bar = (int) buffer[0x8];

    printf("raw: %d\n", buffer[8]);
    printf("foo: %d\n", foo);
    printf("bar: %d\n", bar);
}

And the results from running it:

raw: 8
foo: 185207048
bar: 8
Wes Hardaker
  • 21,735
  • 2
  • 38
  • 69
  • 1
    @cnicutar are you sure? `buffer[0x8]` is dereferencing (buffer + offset). It returns a value, not a pointer. Casting the value to an int pointer would point you who knows where.. – calebds Feb 06 '12 at 18:49
  • @cnicutar, no it's not. It's in fact required. Watch out for any alignment requirements your machine might have if you use this method. – Carl Norum Feb 06 '12 at 18:49
  • buffer[0x8] will return the single byte at the 8th position in the buffer. &buffer[0x8] will return the memory location of the 8th byte in the buffer, which is what needs to be cast. You don't want to dereference the number at buffer 8. – Wes Hardaker Feb 06 '12 at 18:52
  • @Carl Norum Yup, I was wrong :-) Of course it's required (for some reason I read `buffer` instead of `buffer[0x8]`). – cnicutar Feb 06 '12 at 18:53
1

Endianess conversion of a 4byte value is done by changing the two words of that value (16bit), so the less efficient but readable way would be (if data is big endian encoded):

int val = 0x00000000;
char* ptr = reinterpret_cast<char*>(&val);
*ptr = buffer[0x0a];
ptr++;
*ptr = buffer[0x0b];
ptr++;
*ptr = buffer[0x08];
ptr++;
*ptr = buffer[0x09];
ptr++;

But there are many many other ways to do it like structs, memcpy... depending on what is your goal (performace, readability,...)

Best regards, Alex

0
int *list = (int*)buffer;
int n = fread(buffer, 1, size, file);
for (int i=0; i< n/sizeof(int); i++)
  printf("%d\n", list[i]);
perreal
  • 94,503
  • 21
  • 155
  • 181