Solved

extra bytes

Posted on 2014-03-17
11
278 Views
Last Modified: 2014-03-21
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
Comment
Question by:mastiSoft
  • 2
  • 2
  • 2
  • +4
11 Comments
 
LVL 74

Expert Comment

by:käµfm³d 👽
ID: 39934352
I'm no C++ expert, but don't structures get padded to fit word boundaries?
0
 
LVL 142

Expert Comment

by:Guy Hengel [angelIII / a3]
ID: 39934354
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
 
LVL 19

Expert Comment

by:Ken Butters
ID: 39934379
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
 
LVL 32

Expert Comment

by:phoffric
ID: 39934822
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
 
LVL 19

Expert Comment

by:Ken Butters
ID: 39934844
@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
How to run any project with ease

Manage projects of all sizes how you want. Great for personal to-do lists, project milestones, team priorities and launch plans.
- Combine task lists, docs, spreadsheets, and chat in one
- View and edit from mobile/offline
- Cut down on emails

 
LVL 32

Assisted Solution

by:sarabande
sarabande earned 250 total points
ID: 39934928
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
 
LVL 24

Accepted Solution

by:
chaau earned 250 total points
ID: 39935468
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
 
LVL 1

Author Closing Comment

by:mastiSoft
ID: 39936476
Thank you very much, now it works as it have to .
0
 
LVL 32

Expert Comment

by:sarabande
ID: 39936912
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
 
LVL 1

Author Comment

by:mastiSoft
ID: 39945126
Yes I will  spread the points evenly between Ken Butters, phoffric and Sara
0

Featured Post

6 Surprising Benefits of Threat Intelligence

All sorts of threat intelligence is available on the web. Intelligence you can learn from, and use to anticipate and prepare for future attacks.

Join & Write a Comment

When writing generic code, using template meta-programming techniques, it is sometimes useful to know if a type is convertible to another type. A good example of when this might be is if you are writing diagnostic instrumentation for code to generat…
Introduction This article is a continuation of the C/C++ Visual Studio Express debugger series. Part 1 provided a quick start guide in using the debugger. Part 2 focused on additional topics in breakpoints. As your assignments become a little more …
The viewer will learn how to pass data into a function in C++. This is one step further in using functions. Instead of only printing text onto the console, the function will be able to perform calculations with argumentents given by the user.
The viewer will be introduced to the technique of using vectors in C++. The video will cover how to define a vector, store values in the vector and retrieve data from the values stored in the vector.

744 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

14 Experts available now in Live!

Get 1:1 Help Now