Thread: Struct size incorrect

  1. #1
    Registered User
    Join Date
    Aug 2003
    Posts
    21

    Struct size incorrect

    I've created the following struct...

    Code:
    typedef struct {
    	short 	type;
    	int 	fileSize;
    	short 	res0;
    	short 	res1;
    	int 	dataOffset;
    } BMPFILEHEADER;
    By my calculations, it should equal 14 bytes. Two bytes for each short and four bytes for each int. The thing is, if I do sizeof(BMPFILEHEADER) it equals 16 and I have no clue why. Especially when if I do sizeof(int) and sizeof(short) they come out at four bytes and two bytes respectively

    I'm using gcc in Cygwin as my compiler, if that makes a difference. I'm downloading the express edition of Visual C++ 2008 as I write this to see if that makes a difference.

    Any ideas?

  2. #2
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,665
    The compiler is free to add "padding" bytes between members of the structure to preserve alignment requirements of the various data types.

    Aligned data is often more efficiently accessed than unaligned data.

    A search for "padding and alignment" should find more information.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  3. #3
    Registered User
    Join Date
    Aug 2003
    Posts
    21
    Ah, right. I seem to remember reading something about this a while ago. Isn't there some kind of pragma directive I can add to stop it from doing this?

  4. #4
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    You usually don't want to do that since it optimizes for the processor to access data.
    Otherwise look in your compiler's settings, because it's different for each compiler.

  5. #5
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,665
    There may be, but the syntax varies from compiler to compiler.

    #pragma pack(1)
    For example.

    Even if that solves the size problem, you may have to solve the endian problem as well.

    The only truly portable answer is to read the file a byte at a time and move that byte to the correct location in the struct.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  6. #6
    Registered User
    Join Date
    Oct 2007
    Posts
    38
    hehe, i just came here to ask absolutely the same question...
    I have a structure (a string of 50 bytes, a double of 4 bytes and an int of 4 bytes)...
    Code:
    typedef struct product {
    	char name[50];
    	float price;
    	int quantity;
    };
    I kept getting 60 bytes when i checked its size instead of 58. Now i know why...

    P.S. sorry to hijack your thread redneon, but what if i wanted to read the second piece of the structure (i.e. price), what should the offset be?

    [name][padding][price][padding][quantity]
    __50__+___1___+__4__+___1___+___4___ = 60 bytes

  7. #7
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Depends on the padding. Again, to be safe, just let the compiler do its work. Access the member by its name, and it will work fine.
    Code:
    struct product prod;
    prod.price = 1.50;

  8. #8
    Registered User
    Join Date
    Oct 2007
    Posts
    38
    Sorry, i shoudl've been clearer... If I had written the structure into a file and then wanted to access only the price (to edit it for example)... Would I use something of this sort?
    Code:
    fseek(file_pointer, sizeof(product.name) + 1, SEEK_SET)

  9. #9
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Once again, depends on padding. You can do trial & error, but the safest way is to write the entire struct and read the entire struct from the file, unchanged. This also takes into account that you did not change padding settings and that you did not change endianness - ie trying to read an existing file on another platform.
    I'm not sure how much or where the padding is, but you could find it by doing like this:

    Code:
    struct product prod;
    int off = &prod.price - ∏ // Calculate offset of price inside the struct of prod.

  10. #10
    Algorithm Dissector iMalc's Avatar
    Join Date
    Dec 2005
    Location
    New Zealand
    Posts
    6,318
    Quote Originally Posted by Karpaty View Post
    [name][padding][price][padding][quantity]
    __50__+___1___+__4__+___1___+___4___ = 60 bytes
    NO, it wont be like that. It will be like this:
    [name][padding][price][quantity]
    __50__+___2___+__4__+___4___ = 60 bytes
    The compiler doesn't just artibrarily stick extra bytes between fields. It puts them in specific places to align fields to word or dword boundaries etc.
    My homepage
    Advice: Take only as directed - If symptoms persist, please see your debugger

    Linus Torvalds: "But it clearly is the only right way. The fact that everybody else does it some other way only means that they are wrong"

  11. #11
    Registered User
    Join Date
    Oct 2007
    Posts
    38
    Oh, thanks for clearing that up...
    btw, Elysia, I have this function to add a new product:

    Code:
    void add_product(product *p) {
    	printf("Enter product description : ");
    	gets(p->name);
    	printf("Enter price per unit (cent) : ");
    	scanf("%f", &p->price);
    	printf("Enter stock level: ");
    	scanf("%d", &p->quantity);
    }
    if I wanted to modify just the price, would the following function work? (Thats assuming I moved the offset to the start of the product structure)...

    Code:
    void edit_price(product *p) {
    	printf("Enter price per unit (cent) : ");
    	scanf("%f", &p->price);
    }
    The code is pretty much the same apart the left out name and quantity parts...

  12. #12
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Yes, it would work, even if you don't move the price to start of the structure.
    Why? Because it reads the address of &price, and not the address of the structure start.

  13. #13
    Registered User
    Join Date
    Oct 2007
    Posts
    38
    Cheers... I've been struggling with this problem all weekend... Will now try and put the theory in practice

  14. #14
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Good luck.

  15. #15
    Ex scientia vera
    Join Date
    Sep 2007
    Posts
    477
    I know for a fact that the Mingw port of GCC, and GCC support the following format:

    Code:
    struct foobar {
    
         int yo;
    
         char homie;
    
    }__attribute__ ((packed));

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. char Handling, probably typical newbie stuff
    By Neolyth in forum C Programming
    Replies: 16
    Last Post: 06-21-2009, 04:05 AM
  2. Assignment HELP!!
    By cprogrammer22 in forum C Programming
    Replies: 35
    Last Post: 01-24-2009, 02:24 PM
  3. Adventures in labyrinth generation.
    By guesst in forum Game Programming
    Replies: 8
    Last Post: 10-12-2008, 01:30 PM
  4. Replies: 10
    Last Post: 05-18-2006, 11:23 PM
  5. Replies: 11
    Last Post: 03-25-2003, 05:13 PM