C语言结构体对齐

1.结构体变量中的元素如何访问?

(1)数组中元素的访问方式:表面上有2种方式(数组下标方式和指针方式);实质上都是指针方式访问。
(2)结构体变量中的元素访问方式:只有一种,用.或者->的方式来访问。(.和->访问结构体元素其实质是一样的,只是C语言规定用结构体变量来访问元素用. 用结构体变量的指针来访问元素用->。实际上在高级语言中已经不区分了,都用.)
(3)结构体的访问方式有点类似于数组下标的方式

2.利用指针访问结构体元素

  结构体元素地址=结构体首地址+元素偏移量

  

struct mystruct
{
    int a;
    int b;            

} s1;

//s1.b的地址
int* p=(int*)((int)&s1+4);
*p=5;// s1.b=5;

3.结构体对齐

  一般情况下,为了配合硬件,如果对齐排布和访问会提高效率,否则会大大降低效率。

  (0)、一般编辑器默认4字节对齐。

  (1)、结构体对齐要考虑:结构体整体本身必须安置在4字节对齐处,结构体对齐后的大小必须4的倍数(编译器设置为4字节对齐时,如果编译器设置为8字节对齐,则这里的4是8)
  (2)、结构体中每个元素本身都必须对其存放,而每个元素本身都有自己的对齐规则。
  (3)、编译器考虑结构体存放时,以满足以上2点要求的最少内存需要的排布来算。

struct mystruct1
{                      // 1字节对齐    4字节对齐
    int a;         // 4            4
    char b;              // 1            2(1+1)
    short c;            // 2            2
}; 

struct mystruct11
{                     // 1字节对齐    4字节对齐
    int a;            // 4            4
    char b;           // 1            2(1+1)
    short c;         // 2            2
};

typedef struct mystruct111
{                    // 1字节对齐    4字节对齐        2字节对齐
    int a;            // 4            4                4
    char b;          // 1            2(1+1)            2
    short c;         // 2            2                2
    short d;         // 2            4(2+2)            2
} My111;

typedef struct mystruct2
{                    // 1字节对齐    4字节对齐
    char a;           // 1            4(1+3)
    int b;            // 4            4
    short c;         // 2            4(2+2)
}MyS2;

struct mystruct21
{                    // 1字节对齐    4字节对齐
    char a;            // 1           4(1+3)
    int b;            // 4            4
    short c;          // 2            4(2+2)
} ;
typedef struct myStruct5
{                            // 1字节对齐    4字节对齐
    int a;                    // 4          4
    struct mystruct1 s1;    // 7            8
    double b;                // 8           8
    int c;                    // 4          4
}MyS5;

struct stu
{                            // 1字节对齐    4字节对齐
    char sex;                // 1            4(1+3)
    int length;                // 4            4
    char name[10];            // 10            12(10+2)
};

4.结构体对齐指令

  以#prgama pack(n)开头,以#pragma pack()结尾,定义一个区间,这个区间内的对齐参数就是n。

#pragma pack(2)

struct s
{
    char c;            //2 (1+1)
    int b;             //4 (4)

} ;
#pragma pack()

  取消对齐访问
  __attribute__((packed));
  设置结构体整体对齐访问(不包含元素)
  __attribute__((aligned(n)));

  

struct mystruct11
{                    // 1字节对齐    4字节对齐
    int a;            // 4            4
    char b;            // 1            2(1+1)
    short c;        // 2            2
}__attribute__((packed));

typedef struct mystruct111
{                    // 1字节对齐    4字节对齐        2字节对齐
    int a;            // 4            4                4
    char b;            // 1            2(1+1)            2
    short c;        // 2            2                2
    short d;        // 2            4(2+2)            2
}__attribute__((aligned(1024))) My111;

5.offsetof宏与container_of宏

offsetof            在0地址处虚拟出一个结构体,通过元素的地址则为偏移量

container_of     通过元素地址减去偏移量得到结构体地址

typeof()传入变量,返回相应的数据类型。
#include<stdio.h>

struct mystruct
{
    char a;
    int b;
    short c;

};
// TYPE是结构体类型,MEMBER是结构体中一个元素的元素名
// 这个宏返回的是member元素相对于整个结构体变量的首地址的偏移量,类型是int
#define offsetof(TYPE, MEMBER) ((int) &(((TYPE *)0)->MEMBER))//TYPE *为传入值 

 // ptr是指向结构体元素member的指针,type是结构体类型,member是结构体中一个元素的元素名
// 这个宏返回的就是指向整个结构体变量的指针,类型是(type *)
//typeof() 是通过变量名 返回数据类型的
#define container_of(ptr, type, member) ({                const typeof(((type *)0)->member) * __mptr = (ptr);    \  //定义一个typeof(((type *)0)->member)类型的指针指向 结构体元素地址
    (type *)((char *)__mptr - offsetof(type, member)); })  //元素地址-偏移量=结构体首地址
    //通过元素地址减去偏移量得到结构体地址
int main()
{
    struct mystruct s1;
    struct mystruct *Ps;
    s1.b=12;
    int * pb=&s1.b;
    Ps=container_of(pb,struct mystruct,b);
    printf("container_of宏实例\n");
    printf("&s1=%p\n",&s1);
    printf("Ps=%p\n",Ps);

    //int *p=(int *)((char*)&s1+4);
    int *p=(int *)((int)&s1+4);
    printf("*p=%d.\n",*p);
    printf("offsetof宏实例\n");
    int offsetof_a=offsetof(struct mystruct,a);
    int offsetof_b=offsetof(struct mystruct,b);
    int offsetof_c=offsetof(struct mystruct,c);
    printf("offsetof_a=%d\n",offsetof_a);
    printf("offsetof_b=%d\n",offsetof_b);
    printf("offsetof_c=%d\n",offsetof_c);

    return 0;    

}
时间: 2024-12-25 15:17:29

C语言结构体对齐的相关文章

解析C语言结构体对齐(内存对齐问题)

C语言结构体对齐也是老生常谈的话题了.基本上是面试题的必考题.内容虽然很基础,但一不小心就会弄错.写出一个struct,然后sizeof,你会不会经常对结果感到奇怪?sizeof的结果往往都比你声明的变量总长度要大,这是怎么回事呢? 开始学的时候,也被此类问题困扰很久.其实相关的文章很多,感觉说清楚的不多.结构体到底怎样对齐? 有人给对齐原则做过总结,具体在哪里看到现在已记不起来,这里引用一下前人的经验(在没有#pragma pack宏的情况下): 原则1.数据成员对齐规则:结构(struct或

C语言之结构体以及结构体对齐访问

1:简单理解,结构体就是数组的进一步发展,数据的优点和缺陷在于数据里面是元素类型必须相同,但是结构体没有这个要求,结构体里面元素的类型可以相同也可以不同. 2:结构体的定义: struct student {     int age;     char name[20]; }s1; 上面这种方法是结构体定义的同时定义变量,结构体的定义有两部分组成 struct studen:结构体的类型 s1:类型为struct student的结构体变量,当然还可以用struct studet s2:l来定义

C语言结构体的字节对齐原则

转载:http://blog.csdn.net/shenbin1430/article/details/4292463 为什么要对齐? 现代计算机中内存空间都是按照byte划分的,从理论上讲似乎对任何类型的变量的访问可以从任何地址开始,但实际情况是在访问特定类型变量的时候经常在特 定的内存地址访问,这就需要各种类型数据按照一定的规则在空间上排列,而不是顺序的一个接一个的排放,这就是对齐. 对齐的作用和原因:各个硬件平台对存储空间的处理上有很大的不同.一些平台对某些特定类型的数据只能从某些特定地址

【转】C语言结构体的字节对齐原则

原文链接:http://blog.csdn.net/shenbin1430/article/details/4292463 为什么要对齐? 现代计算机中内存空间都是按照byte划分的,从理论上讲似乎对任何类型的变量的访问可以从任何地址开始,但实际情况是在访问特定类型变量的时候经常在特 定的内存地址访问,这就需要各种类型数据按照一定的规则在空间上排列,而不是顺序的一个接一个的排放,这就是对齐. 对齐的作用和原因:各个硬件平台对存储空间的处理上有很大的不同.一些平台对某些特定类型的数据只能从某些特定

漫谈C语言结构体struct、公用体union空间占用

先用代码说话: #include<stdio.h> union union_data0{ int a ;//本身占用4个字节 char b ;//本身占用1个字节 int c ; }; union union_data1{ short a;//本身占用2个字节 char b[13];//本身占用13个字节 int c ;//本身占用4个字节 }; struct struct_data{ int a ;//int本身占用4个字节,偏移量为0 char b ;//char本身占用1个字节,偏移量为

读陈浩的《C语言结构体里的成员数组和指针》总结,零长度数组

原文链接:C语言结构体里的成员数组和指针 复制如下: 单看这文章的标题,你可能会觉得好像没什么意思.你先别下这个结论,相信这篇文章会对你理解C语言有帮助.这篇文章产生的背景是在微博上,看到@Laruence同学出了一个关于C语言的题,微博链接.微博截图如下.我觉得好多人对这段代码的理解还不够深入,所以写下了这篇文章. 为了方便你把代码copy过去编译和调试,我把代码列在下面: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 #include <stdio.h>

不可或缺 Windows Native (8) - C 语言: 结构体,共用体,枚举,类型定义符

[源码下载] 作者:webabcd 介绍不可或缺 Windows Native 之 C 语言 结构体 共用体 枚举 类型定义符 示例cStruct.h #ifndef _MYHEAD_STRUCT_ #define _MYHEAD_STRUCT_ #ifdef __cplusplus extern "C" #endif char *demo_cStruct(); #endif cStruct.c /* * 结构体,共用体,枚举,类型定义符 * * 注:结构体变量在做参数传递时,其内每个

C语言 结构体存储空间分配

这两天在看结构体,一直在琢磨结构体的存储空间分配的问题,琢磨了半天总算明白了.和大家分享一下,希望能有所帮助.相信大家都知道结构体里元素存储要对齐吧,话虽是没错,只是这个"对齐"里面包含了很多微妙的东西.首先详细的给出结构体内存存储空间分配的原则吧:编译器按照成员列表顺序一个接一个地给每个成员分配内存.只有当存储成员时需要满足正确的边界对齐要求时,成员之间才可能出现用于填充的额外内存空间.而且还有3点要求:结构体变量的首地址要能够被其最宽基本类型元素的大小所整除.结构体的每个元素相对于

C语言结构体(struct)常见使用方法

基本定义:结构体,通俗讲就像是打包封装,把一些有共同特征(比如同属于某一类事物的属性,往往是某种业务相关属性的聚合)的变量封装在内部,通过一定方法访问修改内部变量. 结构体定义: 第一种:只有结构体定义 [cpp] view plain copy struct stuff{ char job[20]; int age; float height; }; 第二种:附加该结构体类型的“结构体变量”的初始化的结构体定义 [cpp] view plain copy //直接带变量名Huqinwei st