繁体   English   中英

C中的结构内存对齐

[英]Structure memory alignment in C

我对以下C程序有疑问

码:

#include <stdio.h>
#include <stdlib.h>

int main()
{
    struct a
    {
        char arr[10];
        int i;

        float b;
    }v[2];

    printf("\n %d   %d  %d  \n",v[0].arr, &v[0].i, &v[0].b);
    printf("\n %d   %d  %d  \n",v[1].arr, &v[1].i, &v[1].b);


    printf("\nHello world!\n");
    return 0;
}

输出:

 2686712   2686724  2686728

 2686732   2686744  2686748

 Hello world!

问题:v [0] .arr == 2686712和arr [10]的大小为10字节&v [0] .i <<<<此地址应在数组..之后立即开始,因为array为10字节.. &v [0] .i的地址应从2686712 + 10开始,即2686722为什么&v [0] .i == 2686724而不是2686722

允许编译器在结构的成员之间或末尾(但不能在开头)插入填充。 根据C99标准草案第6.7.2.1节“ 结构和联合说明符”13段,其中( 强调我的 ):

在结构对象中,非位字段成员和位字段所在的单元的地址按照声明的顺序增加。 指向经过适当转换的结构对象的指针指向其初始成员(或者,如果该成员是位字段,则指向它所驻留的单元),反之亦然。 结构对象内可能存在未命名的填充,但在其开始处没有。

和第15段:

在结构或联合的末尾可能有未命名的填充。

通过对指针使用%d格式说明符,您正在调用未定义的行为 ,则应使用%p

编译器填充结构成员以使每种数据类型的内容正确对齐。

有关结构填充实际上如何工作的信息,请参见此链接 那里有很多非常详细的信息。 另请参阅此链接,以获取针对各种数据类型的英特尔处理器特有的对齐信息。

本质上,因为您有一个10字节的char数组,然后是一个int,所以编译器已在char数组中填充了额外的2个字节,以便int可以在4字节边界上正确对齐(即,地址均匀可被4整除。

就像您这样声明结构:

struct a
{
    char arr[10];
    char _padding[2];
    int i;
    float b;
};

出于习惯,我通常分配的char数组的大小可以被4整除。这样一来,编译器就不必为我做这件事,并且可以更轻松地查看内存中的数据结构。

第一:您不应该使用%d来打印带有printf的指针,而应该使用%p

第二:仅保证结构的第一个元素从结构的地址开始。 任何其他成员都可以插入填充字节,具体取决于编译器和体系结构要求。

大多数编译器默认会将成员的struct元素填充为成员大小。 因此在arr之后将有两个填充字节。

使用struct {...} __attribute__(packed); 如果您希望有一个完整的结构。

在您的系统上,发生4字节对齐。

“ int”和“ float”将占用4个字节,“ char”将占用1个字节

1)在您的问题中,您的结构由于顺序而浪费了2个字节

构造一个{

    char arr[10];
    int i;
    float b;

}v[2];

ANS :: 2)我的解决方法是更改​​“ char arr [10]”的序列,将其放在最后


构造一个

{

     int i;

    float b;

    char arr[10];


}v[2];

现在,如果您要打印地址,那么它将根据您的理解进行打印...

3)内存对齐方式可以根据您的要求(由Compiler使用Google上的“ PRAGMA”搜索“ PRAGMA”提供)进行更改。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM