【问题标题】:How are struct members allocated in memory?结构成员如何在内存中分配?
【发布时间】:2013-12-23 04:54:28
【问题描述】:

在尝试为未来的 C 程序创建内存管理器时,我遇到了这个问题:

“分配结构时,其成员字段是否按照指定的顺序存储?”

例如,考虑以下结构。

typedef struct {
    int field1;
    int field2;
    char field3;
} SomeType;

分配时,字段的内存地址是否会按照字段1、字段2、字段3的顺序排列?还是不能保证?

【问题讨论】:

标签: c memory-management struct


【解决方案1】:

简短回答:它们按照它们在结构中声明的顺序分配。


示例

#include <stdio.h>
#include <string.h>

struct student 
{
    int id1;
    int id2;
    char a;
    char b;
    float percentage;
};

int main() 
{
    int i;
    struct student record1 = {1, 2, 'A', 'B', 90.5};

    printf("size of structure in bytes : %d\n", 
        sizeof(record1));

    printf("\nAddress of id1        = %u", &record1.id1 );
    printf("\nAddress of id2        = %u", &record1.id2 );
    printf("\nAddress of a          = %u", &record1.a );
    printf("\nAddress of b          = %u", &record1.b );
    printf("\nAddress of percentage = %u",&record1.percentage);

    return 0;
}

输出

size of structure in bytes : 16 
Address of id1 = 675376768
Address of id2 = 675376772
Address of a = 675376776
Address of b = 675376777
Address of percentage = 675376780

上述结构内存分配的图示如下。此图将帮助您非常轻松地理解 C 中的内存分配概念。


进一步阅读:查看here(也是上述示例的来源)以获取C – Structure PaddingStructure dynamic memory allocation in C

【讨论】:

    【解决方案2】:

    保证field3field2 之后,field1 之后,并且field1 位于内存的开头(即field1 之前没有填充)。但是,它们可能会在其他成员之间填充(甚至在 field3 之后)。简而言之,它们的声明顺序是它们在内存中的布局顺序,尽管精确对齐和填充是实现定义的(但在第一个成员之前不会有任何填充)。

    【讨论】:

    • 准确来说,保证SomeType x; ((void*) &amp;x) == ((void*) &amp;x.field1).
    • 为什么成员前会有padding!
    • @rullof:成员之前的填充与前一个成员之后的填充相同。如果field1field2 之间有填充,您可以说填充在field1 之后,或者您也可以说在field2 之前有填充。两种说法都不正确;它只取决于视角。但是,如果我误解了您的问题,而您想知道为什么可能有任何填充,那么答案是 all about aligning things in memory with the processors native alignment requirements
    • 我的意思是为什么应该是成员之间的填充。它的目的是什么?
    • @rullof:哎呀;那么在那种情况下,我修改了之前的评论。但是为了进一步扩展,x86 要求 int 在 4 字节边界上对齐(如果 int 是 4 字节),而 char 没有这样的限制(它作为 1 -字节对齐,因此可以在内存中的任何位置)。如果您在char 之后有一个int,则需要3 个字节的填充来确保int 排列在可被4 整除的内存地址上。
    【解决方案3】:
    1. 成员一一定位;
    2. 每个成员的起始位置都应该除以它的长度:

    例如:

    typedef struct {
       char field1;
       int field2;
       double field3;
    } SomeType;
    

    结构体的第一个位置是 x:

    field1的长度为1(byte),filed2为4,field3为8

    所以 field1 在 x+0,field2 在 x+4~x+7,field3 在 x+8~x+15,并且 x+1~x+3 被填充以使 field2 在正确的位置。

    整个结构的长度应该被它的最大成员完全除;如果不是,则在末尾填充一些字节。

    【讨论】:

    • 不,最大成员的长度无关紧要。也许您正在考虑一个 C 联合
    猜你喜欢
    • 2022-11-07
    • 1970-01-01
    • 1970-01-01
    • 2012-08-27
    • 2021-06-04
    • 1970-01-01
    • 2020-10-30
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多