Size of structure with a char, a double, an int an

2019-03-14 12:18发布

This question already has an answer here:

When I run only the code fragment

int *t;
std::cout << sizeof(char)   << std::endl;
std::cout << sizeof(double) << std::endl;
std::cout << sizeof(int)    << std::endl;
std::cout << sizeof(t)      << std::endl;

it gives me a result like this:

1
8
4
4

Total: 17.

But when I test sizeof struct which contains these data types it gives me 24, and I am confused. What are the additional 7 bytes?

This is the code

#include <iostream>
#include <stdio.h>
struct struct_type{
    int i;
    char ch;
    int *p;
    double d;
} s;

int main(){
    int *t;
    //std::cout << sizeof(char)   <<std::endl;
    //std::cout << sizeof(double) <<std::endl;
    //std::cout << sizeof(int)    <<std::endl;
    //std::cout << sizeof(t)      <<std::endl;

    printf("s_type is %d byes long",sizeof(struct struct_type));

    return 0;
}

:EDIT

I have updated my code like this

#include <iostream>
#include <stdio.h>
struct struct_type{
    double d_attribute;
    int i__attribute__(int(packed));
    int * p__attribute_(int(packed));;
    char  ch;
} s;

int main(){
    int *t;
    //std::cout<<sizeof(char)<<std::endl;
    //std::cout<<sizeof(double)<<std::endl;
    //std::cout<<sizeof(int)<<std::endl;
    //std::cout<<sizeof(t)<<std::endl;

    printf("s_type is %d bytes long",sizeof(s));

    return 0;
}

and now it shows me 16 bytes. Is it good, or have I lost some important bytes?

9条回答
混吃等死
2楼-- · 2019-03-14 12:34

The compiler is allowed to align the members of the structure to addresses for faster access. e.g. 32-bit-boundaries. It is only required by the standard, that the members of the object are stored in the order they are declared. So always make sure you use sizeof and offsetof when you need an exact position in memory.

查看更多
家丑人穷心不美
3楼-- · 2019-03-14 12:35

Also sometimes you need the struct to mantain the order you required. In this cases, if you are using gcc, you should use the __attribute__((packed)) statement.

See also this for further info.

查看更多
神经病院院长
4楼-- · 2019-03-14 12:35

$9.2/12 states - "Nonstatic data members of a (non-union) class declared without an intervening access-specifier are allocated so that later members have higher addresses within a class object. The order of allocation of nonstatic data members separated by an access-specifier is unspecified (11.1). Implementation alignment requirements might cause two adjacent members not to be allocated immediately after each other; so might requirements for space for managing virtual functions (10.3) and virtual base classes (10.1)."

So just like the sizeof(double) and sizeof(int), the offsets at which structure members would be aligned is unspecified, except that members that are declared later are at higher addresses.

查看更多
乱世女痞
5楼-- · 2019-03-14 12:45

To expand slightly on KennyDM's excellent answer (Kenny - please do steal this to supplement your answer if you want), this is probably what your memory structure looks like once the compiler has aligned all of the variables:

  0    1    2    3    4    5    6    7
+-------------------+----+-----------+
| i                 | ch | (unused)  |
+-------------------+----+-----------+

  8    9   10   11   12   13   14   15
+-------------------+----------------+
| p                 |   (unused)     |
+-------------------+----------------+

 16   17   18   19   20   21   22   23
+------------------------------------+
| d                                  |
+------------------------------------+

So, because of the 3-byte gap between "ch" and "p", and the 4 byte gap between "p" and "d", you get a 7 byte padding for your structure, thus the size of 24 bytes. Since your environment's double has 8-byte alignment (i.e. it must reside in it's own block of 8-bytes, as you can see above), the entire struct will also be 8-byte aligned over-all, and so even re-ordering the variables will not alter the size from 24 bytes.

查看更多
成全新的幸福
6楼-- · 2019-03-14 12:45

It's 24 bytes due to padding. Most compilers pad data to a multiple of its size. So, a 4-byte int is padded to a multiple of 4 bytes. A 8-byte double is padded to a multiple of 8 bytes. For your structure, this means:

struct struct_type{
  int i; // offset 0 (0*4)
  char ch; // offset 4 (4*1)
  char padding1[3];
  int *p; // offset 8 (2*4)
  char padding1[4];
  double d; // offset 16 (2*8)
}s;

You can optimize your struct like that:

struct struct_type{
  double d;
  int i;
  int *p;
  char ch;
}s;

sizeof(s)==17 on most compilers (20 on some others)

查看更多
孤傲高冷的网名
7楼-- · 2019-03-14 12:47

... it gives me 24, and I am confused. What are the additional 7 bytes?

These are padding bytes inserted by the compiler. Data structure padding is implementation dependent.

From Wikipedia, Data structure alignment:

Data alignment means putting the data at a memory offset equal to some multiple of the word size, which increases the system's performance due to the way the CPU handles memory. To align the data, it may be necessary to insert some meaningless bytes between the end of the last data structure and the start of the next, which is data structure padding.

查看更多
登录 后发表回答