具有 char、double、int 和 at 的结构的大小

发布于 2024-09-14 09:04:18 字数 1504 浏览 11 评论 0原文

当我只运行代码片段时,

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;

它给出的结果如下:

1
8
4
4

总计:17。

但是当我测试包含这些数据类型的 sizeof 结构时,它给出了 24,我很困惑。额外的 7 个字节是多少?

这是代码

#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;
}

:编辑

我已经像这样更新了我的代码

#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;
}

,现在它显示了 16 个字节。这很好,还是我丢失了一些重要的字节?

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?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(9

晚风撩人 2024-09-21 09:04:18

某些成员之间存在一些未使用的字节,以保持对齐正确。例如,为了提高效率,默认情况下指针驻留在 4 字节边界上,即其地址必须是 4 的倍数。如果结构仅包含一个 char 和一个指针,

struct {
  char a;
  void* b;
};

b 无法使用加法器 # 1 — 它必须放置在#4。

  0   1   2   3   4   5   6   7
+---+- - - - - -+---------------+
| a | (unused)  | b             |
+---+- - - - - -+---------------+

在您的情况下,额外的 7 个字节来自由于 int* 对齐而产生的 3 个字节,以及由于 double 对齐而产生的 4 个字节。

  0   1   2   3   4   5   6   7   8   9   a   b   c   d   e   f
+---------------+---+- - - - - -+---------------+- - - - - - - -+
| i             |ch |           | p             |               |
+---------------+---+- - - - - -+---------------+- - - - - - - -+
 10  11  12  13  14  15  16  17
+-------------------------------+
| d                             |
+-------------------------------+

There is some unused bytes between some members to keep the alignments correct. For example, a pointer by default reside on 4-byte boundaries for efficiency, i.e. its address must be a multiple of 4. If the struct contains only a char and a pointer

struct {
  char a;
  void* b;
};

then b cannot use the adderss #1 — it must be placed at #4.

  0   1   2   3   4   5   6   7
+---+- - - - - -+---------------+
| a | (unused)  | b             |
+---+- - - - - -+---------------+

In your case, the extra 7 bytes comes from 3 bytes due to alignment of int*, and 4 bytes due to alignment of double.

  0   1   2   3   4   5   6   7   8   9   a   b   c   d   e   f
+---------------+---+- - - - - -+---------------+- - - - - - - -+
| i             |ch |           | p             |               |
+---------------+---+- - - - - -+---------------+- - - - - - - -+
 10  11  12  13  14  15  16  17
+-------------------------------+
| d                             |
+-------------------------------+
甜点 2024-09-21 09:04:18

...它给了我 24,我很困惑。额外的 7 个字节是多少?

这些是编译器插入的填充字节。数据结构填充取决于实现。

来自维基百科,数据结构对齐

数据对齐意味着将数据放置在等于字大小的某个倍数的内存偏移处,这会由于CPU处理内存的方式而提高系统的性能。要对齐数据,可能需要插入在最后一个数据结构的末尾和下一个数据结构的开始之间存在一些无意义的字节,这是数据结构填充。

... 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.

骄傲 2024-09-21 09:04:18

为了稍微扩展 KennyDM 的出色答案(Kenny - 如果需要,请窃取此内容来补充您的答案),一旦编译器对齐了所有变量,这可能就是您的内存结构的样子:

  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                                  |
+------------------------------------+

所以,因为 3 字节“ch”和“p”之间的间隙,以及“p”和“d”之间的 4 字节间隙,您的结构会得到 7 字节的填充,因此大小为 24 字节。由于您的环境的 double 具有 8 字节对齐(即它必须驻留在自己的 8 字节块中,如上所示),因此整个 struct 也将是总体上 8 字节对齐,因此即使重新排序变量也不会改变 24 字节的大小。

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.

横笛休吹塞上声 2024-09-21 09:04:18

由于填充,它是 24 字节。
大多数编译器将数据填充为其大小的倍数。
因此,4 字节 int 被填充为 4 字节的倍数。
8 字节双精度数被填充为 8 字节的倍数。
对于您的结构,这意味着:

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;

您可以像这样优化您的结构:

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

在大多数编译器上 sizeof(s)==17 (在其他一些编译器上为 20)

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)

十年不长 2024-09-21 09:04:18

编译器可以将结构体的成员与地址对齐,以便更快地访问。例如 32 位边界。标准仅要求对象的成员按照声明的顺序存储。因此,当您需要内存中的精确位置时,请务必使用 sizeofoffsetof

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.

蓝眼泪 2024-09-21 09:04:18

额外的大小来自数据对齐,即成员对齐到 4 或 8 字节的倍数。

您的编译器可能会将 int 和指针对齐到 4 字节的倍数,将 double 对齐到 8 字节的倍数。

如果将双精度数移动到结构中的不同位置,则可能能够将结构的大小从 24 字节减少到 20 字节。但这取决于编译器。

The additional size comes from data alignment, i.e. the members are aligned to multiples 4 or 8 bytes.

Your compiler probably aligns int and pointers to multiples for 4 bytes and the double to multiples for 8 bytes.

If you move the double to a different position within the struct, you might be able to reduce the size of the struct from 24 to 20 bytes. But it depends on the compiler.

夜深人未静 2024-09-21 09:04:18

有时您还需要结构来维持所需的顺序。在这种情况下,如果您使用 gcc,则应使用 __attribute__((packed)) 语句。

另请参阅此了解更多信息。

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.

生活了然无味 2024-09-21 09:04:18

$9.2/12 状态 - “在没有介入访问说明符的情况下声明的(非联合)类的非静态数据成员被分配,以便后面的成员在类对象中具有更高的地址。由访问分隔的非静态数据成员的分配顺序- 未指定说明符 (11.1)。
可能会导致两个相邻的成员不能立即分配;所以可能
管理虚拟函数 (10.3) 和虚拟基类 (10.1) 的空间要求。”

因此,就像 sizeof(double) 和 sizeof(int) 一样,结构体成员对齐的偏移量是未指定的,除了以下成员之外:稍后声明的地址更高。

$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.

凉薄对峙 2024-09-21 09:04:18

参见comp.lang.c常见问题列表·问题2.12

为什么我的编译器会在结构中留下漏洞、浪费空间并阻止对外部数据文件的“二进制”I/O?我可以关闭此功能,或者以其他方式控制结构字段的对齐方式吗?

See comp.lang.c FAQ list · Question 2.12:

Why is my compiler leaving holes in structures, wasting space and preventing ``binary'' I/O to external data files? Can I turn this off, or otherwise control the alignment of structure fields?

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文