1

I have binary file that is represented in hexa e.g

 4d42 b666 000a 0000 0000 0036 0000 0028

The first 4 bytes represent value which i want to extract.

I know i can extract it right

std::ifstream is("img.bmp", std::ifstream::binary);
uint64_t data = 0;
is.read((char*)&data,4)

which would result in 3060157762

However using

  unsigned char * test   = new unsigned char [ 4  ]; 
  is.read((char*)test , 4 );
  uint64_t t = 0;
  for( int i = 0; i < 4;i++){
    t <<= 8; // 2 hexa symbols = 1 byte = 1 char = 8 bits
    t|= test[i];
  }
  cout << t << endl;

this results in 1112368822 which obviously differ.

I wonder how could we achieve same result with second method? What are some bitwise tricks for this? I cannot think of anything besides the method i have shown.

Thanks for help.

Darlyn
  • 4,715
  • 12
  • 40
  • 90
  • Hint : 3060157762 gives 112368822 if you reverse the byte order . Look up [Endianness](https://en.wikipedia.org/wiki/Endianness) – François Andrieux Mar 31 '17 at 13:36
  • Why do you use 8 bytes type to read 4 bytes? On little endian platform that would break your program. – Slava Mar 31 '17 at 13:49
  • @Slava Do you mean unsigned char? Its range is 0-255 so it should be 1 byte , or am i wrong? – Darlyn Mar 31 '17 at 14:19
  • 1
    @trolkura no, I mean that uint64_t is 8 bytes and you read 4 bytes to it. It works on Big Endian, but would break on Little Endian. Just look how the same integer represented in memory for that platforms. – Slava Mar 31 '17 at 14:24
  • @Slava Oh right! thanks for ponting out. – Darlyn Mar 31 '17 at 14:45

1 Answers1

2

First of all, use 4 byte type to store 4 bytes. You dont need 64 bit type. The thing is that you're reversing your number in the loop. Your second method reads 4 bytes into test like that: test[0] = 0x4, test[1] = 0xd, test[2] = 0x4, test[3] = 0x2. What you do then is filling bytes of t in the reverse order, from right to the left. First, you fill the rightmost byte with 0x4, then moving to the left with 0xd, 0x4 and 0x2 accordingly. So you get t == 0x24d4.


Code that does the thing:

unsigned char * test = new unsigned char [4]; 
is.read((char*)test, 4);
uint32_t t = 0;
for(int i = 3; i >= 0; --i) {
    t <<= 8;
    t |= test[i];
}
cout << t << endl;