Improve company productivity with a Business Account.Sign Up

x
  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 297
  • Last Modified:

extra bytes

Hi I try to write 8 bit bmp but found that there is some bytes that wasn't be in file.
After 2 bytes BM always appears 2 extra bytes (and they are not empty). I removed almost everything from code to find where is the problem.

 typedef struct  {
      char B;
      char M;
      int width ;//4 bytes
      int height; //4 bytes
       } BMPHEAD;

     BMPHEAD bh;

    bh.B=0x42;
    bh.M=0x77;
   bh.width =819;
    bh.height= 460;
  file.write ((char*)(&bh), sizeof(bh));

Open in new window


but when I open created file in Hex editor I see 12 bytes not 10 as expected. There is 2 extra bytes (byte 3 and 4).
Can any one tell me what's the problem with my code?
snapshot5.png
0
mastiSoft
Asked:
mastiSoft
  • 2
  • 2
  • 2
  • +4
2 Solutions
 
käµfm³d 👽Commented:
I'm no C++ expert, but don't structures get padded to fit word boundaries?
0
 
Guy Hengel [angelIII / a3]Billing EngineerCommented:
this is due to "padding" of the different byte sizes of the struct parts.

the first 2 being CHAR, each 1 byte, then next ones are int (each 4 bytes), the first 2 bytes are padded with 2 bytes to match ...

so far for the explanation that I remember of my old days in C/C++ ...
not sure about the solution, but I presume you will need some intermediate data structures to solve this ...
0
 
Ken ButtersCommented:
As an old mainframe assembler programmer... I do remember Fullwords / Halfword etc being important... but didn't think that taken into account in C++... but maybe it still is.

If it is a full word boundary issue, I think the issue would "go away" if you swap the order of the items in your typedef.

typedef struct  {
      int width ;//4 bytes
      int height; //4 bytes
      char B;
      char M;
       } BMPHEAD;
0
Get your problem seen by more experts

Be seen. Boost your question’s priority for more expert views and faster solutions

 
phoffricCommented:
Using Ken Butters revision, in Visual Studio, the following code produced sizeB = 12, instead of 10.
   size_t sizeB = sizeof( BMPHEAD );
   printf( "sizeof(BMPHEAD) = %d\n", sizeB);

Open in new window

There are still two bytes of padding at the end of the struct. This allows for arrays of BMPHEAD to be defined and then still have width laid out on a 4-byte boundary. The reason for the alignment in x86 is performance improvements. Some other processor require proper alignment and packing is not permitted.

In general to have a minimal memory footprint for a struct, you put the largest types first (e.g., double) and then the next largest (e.g., float or long), working down to the smallest.

By adding a #pragma pack(1) directive to Visual Studio code, then there was no packing and the size of the struct is 10 on my platform.
0
 
Ken ButtersCommented:
@phoffric --- I think you nailed it exactly. Nice!

In most cases, I'd say you should use the pack directive with extreme prejudice, because you are likely to cause errors on some platforms.... however since it looks like in this case were are dealing with a BMP file which would require a very specific layout... it would be an ideal use of the #pragma pack(1) directive.

again... nice find @Phoffric!
0
 
sarabandeCommented:
to add to above comments:

the default alignment of members of a struct or class in c/c++ is 8-bytes for many compilers. that means that a new member with a size of 8-bytes or more always starts at an address that can be divided by 8 without rest. the possible gap to a previous member was padded by zeros.  if the new member was smaller than 8-byte it was aligned according to its size. for a 32-bit integer it means it would be aligned at the next 4-byte boundary. that is what you experienced. because of that, if you order the members by their size, biggest first, it is a good chance that the structure was packed beside you were using 'odd' array sizes or class members with an odd size (see also comments of Ken Butters and phoffric).

also, all compilers and ide's have an option to get structures packed and have no padding then. if using visual c++ you would go to c++ properties of the project and set the property 'Struct Member Alignment' in tab 'Code Generation' to '1 Byte' what would add '/Zp1' to the compiler options. the #pragma pack alternative would move the solution to the source code what could have advantages (for example you could handle it in one header file) or disadvantages (it is not portable and not necessarily the place where other developers would look for it).

Sara
0
 
chaauCommented:
To add to the Sara's comments above: If you do not want to change the byte alignment for the whole program, but only want to align bytes within the structure use pragma pack directive, like this:
#pragma pack(1) //1 byte alignment
typedef struct  {
      char B;
      char M;
      int width ;//4 bytes
      int height; //4 bytes
       } BMPHEAD;
#pragma pack() // back to the project default alignment

Open in new window

0
 
mastiSoftAuthor Commented:
Thank you very much, now it works as it have to .
0
 
sarabandeCommented:
mastiSoft, you probably should spread the points evenly between Ken Butters, phoffric, me and chaau who all have posted valid solutions to your question.

Sara
0
 
mastiSoftAuthor Commented:
Yes I will  spread the points evenly between Ken Butters, phoffric and Sara
0
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

Join & Write a Comment

Featured Post

Get expert help—faster!

Need expert help—fast? Use the Help Bell for personalized assistance getting answers to your important questions.

  • 2
  • 2
  • 2
  • +4
Tackle projects and never again get stuck behind a technical roadblock.
Join Now