weird struct size

i have quite a bit of confusion right now,
i have a struct like this (the purpose is for reading a binary data, and this is not full struct, just part of it which is the most important)
1
2
3
4
5
6
7
8
9
10
struct store
{
 int index;
 int code;
 char name[32];
 char product[32];
 char company[32];
 int price;
 int count;
};

if i do cout<<sizeof(store); the size is 116 instead of 112
but if i remove int price from the struct, the size become 108 instead of 112,
it's as if int price; is considered as 8 byte :/ and not 4
but the size of int price itself is 4, so where the hell the other 4 coming from? o.O
and it's only happened to int price;, if i delete int count;, it's considered as 4, so the size from 116 become 112, if i changed price to char price[4]; the size become normal 112, since it's used for reading binary file, the size become problem now :(
hope someone can help :(

PS : my computer is 32 bit and i use win32 platform for this project, it just simple and plain console program
Seems ok. This code isn't quite right, but works on 32bit VS.

I hope it helps. Come back with any questions.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
#include <iostream>

struct store
{
	int		index;
	int		code;
	char	name[32];
	char	product[32];
	char	company[32];
	int		price;
	int		count;
};

std::ostream& show_index(std::ostream& os, store& s)
{
	os	<< int(&s.index)  - int(&s) << ":"
		<< int(&s.index)  - int(&s) + sizeof(s.index) - 1
		<< "\n";
	return os;
}

std::ostream& show_code(std::ostream& os, store& s)
{
	os	<< int(&s.code)  - int(&s) << ":"
		<< int(&s.code)  - int(&s) + sizeof(s.code) - 1
		<< "\n";
	return os;
}

std::ostream& show_name(std::ostream& os, store& s)
{
	os	<< int(&s.name)  - int(&s) << ":"
		<< int(&s.name)  - int(&s) + sizeof(s.name) - 1
		<< "\n";
	return os;
}

std::ostream& show_product(std::ostream& os, store& s)
{
	os	<< int(&s.product)  - int(&s) << ":"
		<< int(&s.product)  - int(&s) + sizeof(s.product) - 1
		<< "\n";
	return os;
}

std::ostream& show_company(std::ostream& os, store& s)
{
	os	<< int(&s.company)  - int(&s) << ":"
		<< int(&s.company)  - int(&s) + sizeof(s.company) - 1
		<< "\n";
	return os;
}

std::ostream& show_price(std::ostream& os, store& s)
{
	os	<< int(&s.price)  - int(&s) << ":"
		<< int(&s.price)  - int(&s) + sizeof(s.price) - 1
		<< "\n";
	return os;
}

std::ostream& show_count(std::ostream& os, store& s)
{
	os	<< int(&s.count)  - int(&s) << ":"
		<< int(&s.count)  - int(&s) + sizeof(s.count) - 1
		<< "\n";
	return os;
}

int main()
{
	store s;
	std::cout << sizeof(s) << "\n";
	std::cout << "s.index = ";   show_index(std::cout, s);
	std::cout << "s.code = ";    show_code(std::cout, s);
	std::cout << "s.name = ";    show_name(std::cout, s);
	std::cout << "s.product = "; show_product(std::cout, s);
	std::cout << "s.company = "; show_company(std::cout, s);
	std::cout << "s.price = ";   show_price(std::cout, s);
	std::cout << "s.count = ";   show_count(std::cout, s);
}
> if i do cout<<sizeof(store); the size is 116 instead of 112
> my computer is 32 bit and i use win32 platform for this project, it just simple and plain console program

I'm (also) not able to reproduce this; sizeof(store) is 112 when I try it.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
#include <iostream>
#include <cstddef>
#include <typeinfo>
#include <cstdint>
#include <limits>

#define SHOW(a) ( std::cout << #a << ": " << (a) )

#define SHOW_MEMBER(S,m) { SHOW( offsetof(S,m) ) ; \
                           std::cout << "  type: " << typeid(S::m).name() << "   " ; \
                           SHOW( sizeof(S::m) ) << '\n' ; }

struct store
{
     int index;
     int code;
     char name[32];
     char product[32];
     char company[32];
     int price;
     int count;
};

int main()
{
    std::cout << "platform: " << std::numeric_limits<std::uintptr_t>::digits << " bits\n" 
              << "msc++ version: " << _MSC_VER << "\n\n" ; 
    SHOW( sizeof(store) ) << "\n\n" ;
    SHOW_MEMBER(store,index) ;
    SHOW_MEMBER(store,code) ;
    SHOW_MEMBER(store,name) ;
    SHOW_MEMBER(store,product) ;
    SHOW_MEMBER(store,company) ;
    SHOW_MEMBER(store,price) ;
    SHOW_MEMBER(store,count) ;
}

platform: 32 bits
msc++ version: 1900

sizeof(store): 112

offsetof(store,index): 0  type: int   sizeof(store::index): 4
offsetof(store,code): 4  type: int   sizeof(store::code): 4
offsetof(store,name): 8  type: char [32]   sizeof(store::name): 32
offsetof(store,product): 40  type: char [32]   sizeof(store::product): 32
offsetof(store,company): 72  type: char [32]   sizeof(store::company): 32
offsetof(store,price): 104  type: int   sizeof(store::price): 4
offsetof(store,count): 108  type: int   sizeof(store::count): 4


http://rextester.com/TMK2295
my problem is solved, but not fixed, i'm still not sure, and unable to understand it either,
in the end, i changed int price to something else, somehow he want the first byte to be char or BYTE, and can't be used for int, still unable to understand it either.
not so sure if something wrong with my project setting
closed account (48T7M4Gy)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include <iostream>

int main()
{
  struct store
  {
    int index;
    int code;
    char name[32];
    char product[32];
    char company[32];
    int price;
    int count;
  };
  
  std::cout << sizeof(store);
}


112 
Exit code: 0 (normal program termination)


This is exactly what you would expect by individual summation on paper the same as all the others have demonstrated by other means. It uses your code just cut and paste, no magic. Can you reproduce here your figure of 116?
Hi,

Wouldn't you have to set up your code to write exactly 32 bytes for those char arrays? I mean the size of the struct is irrelevant for your purpose, you have to take care of each element in the struct individually when doing a binary file.

If the size of each element is important then consider using types found in <cstdint>

http://en.cppreference.com/w/cpp/header/cstdint



Disch wrote an article about binary files:

http://www.cplusplus.com/articles/DzywvCM9/


The only other thing I can think of as to why it is happening in the first place, is a possible issue with data alignment by the compiler, but as I mentioned earlier, I think this is irrelevant for this purpose.

There is also this to see what might be happening:

http://en.cppreference.com/w/cpp/language/alignof

http://en.cppreference.com/w/cpp/language/object


Good Luck !!
look like it's something to do with align? i'm not quite sure, as i'm new to C++
even struct like this have size 20 (which it should 18)
1
2
3
4
5
6
7
8
struct Header
{
	__int16 Kind;
	int totalsize;
	int data;
	int total;
	int price;
};


but after adding and changing to :
1
2
3
4
5
6
7
8
9
10
#pragma pack(push, 1)
struct ItemEDFHeader
{
	__int16 Kind;
	int totalsize;
	int startoffset;
	int block;
	int size;
};
#pragma pack(pop) 

adding pragma pack seem to solve it, and after print the size it's back to normal 18,
have been reading about pragma pack, but aren't understand how this result in different size?
any explanation tho' why the size is different?
Hi,

As I said in my last post, the size of the struct is irrelevant when writing to a binary file, you have to write each element of the struct individually, you are not writing the whole struct as one unit. This is so you can read / write with the same size.

With the alignment in the first example, it looks like the compiler is aligning to a 32 bit boundary, so the 2 byte Kind is padded so it takes up 4 bytes as well. So we have 5 * 4 = 20 bytes.

So you could use the types from <cstdint> , it has int16_t and int32_t for example, that way you know you are getting 16 and 32 bits respectively.

So, IMO you don't have anything to "solve", apart from using those types.

I don't know anything about #pragma pack s.

Good Luck !!
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
#include <iostream>
#include <cstddef>
#include <type_traits>
#include <iomanip>

#define SHOW_MEMBER_OBJECT( S, m ) \
    ( std::cout << "member " #S "::" #m \
                << "  type " << std::setw(13) << typeid(S::m).name() \
                << "  size " << sizeof(S::m) \
                << "  alignment " << alignof( decltype(S::m) ) \
                << "  offset " << std::setw(2) << offsetof(S,m) << '\n' )

int main()
{
    struct A
    {
        short s ;         // size 2  alignment 2  offset  0
                          // pad  2               offset  2
        int v ;           // size 4  alignment 4  offset  4 
        char c ;          // size 1  alignment 1  offset  8 
                          // pad  7               offset  9
        double d ;        // size 8  alignment 8  offset 16
        unsigned char u ; // size 1  alignment 1  offset 24
                          // pad  7               offset 25
    }; // size 32
    
    SHOW_MEMBER_OBJECT( A, s ) ;
    SHOW_MEMBER_OBJECT( A, v ) ; 
    SHOW_MEMBER_OBJECT( A, c ) ;
    SHOW_MEMBER_OBJECT( A, d ) ;
    SHOW_MEMBER_OBJECT( A, u ) ;
    std::cout << "sizeof(A) " << sizeof(A) << "\n---------------------\n\n" ;

    struct B
    {
        short s ;         // size 2  alignment 2  offset  0
        char c ;          // size 1  alignment 1  offset  2  
        unsigned char u ; // size 1  alignment 1  offset  3
        int v ;           // size 4  alignment 4  offset  4  
        double d ;        // size 8  alignment 8  offset  8  
    }; // size 16 
    
    SHOW_MEMBER_OBJECT( B, s ) ;
    SHOW_MEMBER_OBJECT( B, c ) ;
    SHOW_MEMBER_OBJECT( B, u ) ;
    SHOW_MEMBER_OBJECT( B, v ) ;
    SHOW_MEMBER_OBJECT( B, d ) ;
    std::cout << "sizeof(B) " << sizeof(B) << "\n---------------------\n\n" ;

    #pragma pack(1)
    struct C
    {
        short s ;         // size 2  alignment 2(1)  offset  0
        int v ;           // size 4  alignment 4(1)  offset  2  
        char c ;          // size 1  alignment 1     offset  6
        double d ;        // size 8  alignment 8(1)  offset  7  
        unsigned char u ; // size 1  alignment 1     offset 15
    }; // size 16
    
    SHOW_MEMBER_OBJECT( C, s ) ;
    SHOW_MEMBER_OBJECT( C, v ) ;
    SHOW_MEMBER_OBJECT( C, c ) ;
    SHOW_MEMBER_OBJECT( C, d ) ;
    SHOW_MEMBER_OBJECT( C, u ) ;
    std::cout << "sizeof(C) " << sizeof(C) << "\n---------------------\n\n" ;

    #pragma pack(2)
    struct D
    {
        short s ;          // size 2  alignment 2     offset  0
        int v ;            // size 4  alignment 4(2)  offset  2
        char c ;           // size 1  alignment 1     offset  6   
                           // pad  1                  offset  7
        double d ;         // size 8  alignment 8(2)  offset  8
        unsigned char u ;  // size 1  alignment 1     offset 16
                           // pad  1                  offset 17
    }; // size 18
    
    SHOW_MEMBER_OBJECT( D, s ) ;
    SHOW_MEMBER_OBJECT( D, v ) ;
    SHOW_MEMBER_OBJECT( D, c ) ;
    SHOW_MEMBER_OBJECT( D, d ) ;
    SHOW_MEMBER_OBJECT( D, u ) ;
    std::cout << "sizeof(D) " << sizeof(D) << "\n---------------------\n\n" ;
}

member A::s  type         short  size 2  alignment 2  offset  0
member A::v  type           int  size 4  alignment 4  offset  4
member A::c  type          char  size 1  alignment 1  offset  8
member A::d  type        double  size 8  alignment 8  offset 16
member A::u  type unsigned char  size 1  alignment 1  offset 24
sizeof(A) 32
---------------------

member B::s  type         short  size 2  alignment 2  offset  0
member B::c  type          char  size 1  alignment 1  offset  2
member B::u  type unsigned char  size 1  alignment 1  offset  3
member B::v  type           int  size 4  alignment 4  offset  4
member B::d  type        double  size 8  alignment 8  offset  8
sizeof(B) 16
---------------------

member C::s  type         short  size 2  alignment 2  offset  0
member C::v  type           int  size 4  alignment 4  offset  2
member C::c  type          char  size 1  alignment 1  offset  6
member C::d  type        double  size 8  alignment 8  offset  7
member C::u  type unsigned char  size 1  alignment 1  offset 15
sizeof(C) 16
---------------------

member D::s  type         short  size 2  alignment 2  offset  0
member D::v  type           int  size 4  alignment 4  offset  2
member D::c  type          char  size 1  alignment 1  offset  6
member D::d  type        double  size 8  alignment 8  offset  8
member D::u  type unsigned char  size 1  alignment 1  offset 16
sizeof(D) 18
---------------------

http://rextester.com/QTAL74055
http://coliru.stacked-crooked.com/a/4db49f2c28a7dd75
Topic archived. No new replies allowed.