0

I am learning C language and after some days now I am thinking to learn image processing and I started with BMP images and found many tutorials like How to read and write BMP image with C program but I have some doubts in my mind.

This line in code int width = *(int*)&header[18]

Yes I know what is happening in above code but what about 19,20 and 21 byte ? 18 byte is enough for width ? We can get width by just getting the content of 18 element ?

Ahmed Masud
  • 21,655
  • 3
  • 33
  • 58
Aux
  • 85
  • 2
  • 3
  • 10
  • BITMAPHEADER is fully documented. Did you try a google search for it? – Ken White Jun 19 '18 at 02:22
  • Yes but I am confused with arrays representation of header – Aux Jun 19 '18 at 02:23
  • `&header[18]` is an address. You could write it as `(header + 18)`. – rici Jun 19 '18 at 02:31
  • you need to learn about how pointer arithmetic as well as how referencing a memory location with different *basic type* pointers works in C. This question has nothing to do with BMPs it has to do with pointer arithmetic. Also, you actually *don't know* what's happening at that line — otherwise you wouldn't post a question about it :-) just sayin' – Ahmed Masud Jun 19 '18 at 02:34
  • 2
    This code is [undefined behaviour](https://stackoverflow.com/a/4105123/1505939) (strict aliasing violation). Anything may happen, a reasonably common manifestation of this UB is to read four bytes. Any tutorial featuring this code is rubbish – M.M Jun 19 '18 at 02:54
  • This seems like it may also fail on platforms which don't support unaligned access, if `&header[18]` is not aligned to a multiple of your platform's word size. – vgru Jun 19 '18 at 05:25
  • In addition to the strict aliasing issue, using `int` to express 4 raw byte values is also rubbish. You need to use unsigned types. – Lundin Jun 19 '18 at 14:49
  • Further study for the people who wrote the "tutorial": [What is the strict aliasing rule?](https://stackoverflow.com/questions/98650/what-is-the-strict-aliasing-rule). – Lundin Jun 19 '18 at 14:52

1 Answers1

0

It is taking the address of the 18. byte and then reads a 4 byte long integer at that address, so it does read byte 19, 20 and 21 as well.

  • header is a pointer to the place in memory where the BMP header is stored in bytes
  • header[18] means the same as *(header + 18), we add 18 to the address and read the value at that address, tha * operator so called dereferences the pointer
  • &header[18]: take the address of that value, same as header + 18, but some people find this form more expressive
  • (int*)&header[18]: so far we worked with char* pointers (pointers that point to memory that hold values type of char), now we cast this pointer to an int pointer, this doesn't modify anything in the memory, it just changes the way we interpret the data underlying the pointer
  • *(int*)&header[18]: dereference the int* to get the value of the integer at the header + 18 memory address, and since int is 4 byte long on your platform, this will result in loading 4 bytes into the variable width

So we could simplify the expression like this: *(int*)(header + 18). This way its not as misleading and easy to be mistaken for only reading 1 bytes.

The reason we need to cast header to an int* is because the type of header is char*, dereferencing that would really only read a single byte.

krisz
  • 2,686
  • 2
  • 11
  • 18
  • You have a good answer, please expand your answer a bit more to show a working example. – Ahmed Masud Jun 19 '18 at 02:37
  • @krisz Nice explanation thnx now I am able to understand the all logic :) – Aux Jun 19 '18 at 04:07
  • `*(int*)&header[18]` creates a strict aliasing violation, and even if it didn't, it will write data into the sign bit of the int. Similarly, `char` cannot be used for bitmaps since it has implementation-defined signedness. This is 3 different fatal bugs. – Lundin Jun 19 '18 at 14:50