Solved

extra bytes

Posted on 2014-03-17
11
282 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 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
Courses: Start Training Online With Pros, Today

Brush up on the basics or master the advanced techniques required to earn essential industry certifications, with Courses. Enroll in a course and start learning today. Training topics range from Android App Dev to the Xen Virtualization Platform.

 
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

Live: Real-Time Solutions, Start Here

Receive instant 1:1 support from technology experts, using our real-time conversation and whiteboard interface. Your first 5 minutes are always free.

Question has a verified solution.

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

Written by John Humphreys C++ Threading and the POSIX Library This article will cover the basic information that you need to know in order to make use of the POSIX threading library available for C and C++ on UNIX and most Linux systems.   [s…
This article will show you some of the more useful Standard Template Library (STL) algorithms through the use of working examples.  You will learn about how these algorithms fit into the STL architecture, how they work with STL containers, and why t…
The goal of the tutorial is to teach the user how to use functions in C++. The video will cover how to define functions, how to call functions and how to create functions prototypes. Microsoft Visual C++ 2010 Express will be used as a text editor an…
The viewer will learn how to user default arguments when defining functions. This method of defining functions will be contrasted with the non-default-argument of defining functions.

785 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