Solved

extra bytes

Posted on 2014-03-17
11
286 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 75

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 143

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
Networking for the Cloud Era

Join Microsoft and Riverbed for a discussion and demonstration of enhancements to SteelConnect:
-One-click orchestration and cloud connectivity in Azure environments
-Tight integration of SD-WAN and WAN optimization capabilities
-Scalability and resiliency equal to a data center

 
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
 
LVL 33

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 33

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

Free Tool: Subnet Calculator

The subnet calculator helps you design networks by taking an IP address and network mask and returning information such as network, broadcast address, and host range.

One of a set of tools we're offering as a way of saying thank you for being a part of the community.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

IntroductionThis article is the second in a three part article series on the Visual Studio 2008 Debugger.  It provides tips in setting and using breakpoints. If not familiar with this debugger, you can find a basic introduction in the EE article loc…
This article shows you how to optimize memory allocations in C++ using placement new. Applicable especially to usecases dealing with creation of large number of objects. A brief on problem: Lets take example problem for simplicity: - I have a G…
The goal of the video will be to teach the user the difference and consequence of passing data by value vs passing data by reference in C++. An example of passing data by value as well as an example of passing data by reference will be be given. Bot…
The viewer will learn how to use the return statement in functions in C++. The video will also teach the user how to pass data to a function and have the function return data back for further processing.

789 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