C理解(三):结构体,共用体,枚举

本文主要探讨结构体,共用体,枚举等知识。

结构体
        结构体元素访问本质是指针方式,依据元素在结构体中的偏移量和元素类型进行访问
        元素占字节数和类型占字节数不同,导致结构体的元素偏移量要复杂,因此结构体需要对齐访问

结构体对齐规则
        结构体本身应在在4字节对齐处(占4个字节)
        每个元素都对其存放
        结构体对齐后的大小必须4的倍数

gcc对齐指令
        #prgama pack(n)开头,#pragma pack()结尾,区间内n字节对齐,默认4字节对齐
        attribute((packed)):packed取消对齐访问
        attribute((aligned(n))):n字节对齐(整体结构体n字节对齐,即结构体占字节数)

offsetof宏
        作用:计算结构体元素距离结构体首地址的偏移量
        原理:虚拟type类型结构体,type.member访问元素,得到member相对首地址偏移量
        原型:#define offsetof(TYPE, MEMBER) ((size_t)&((TYPE *)0)->MEMBER)
        (TYPE *)0    
                0强制类型转换TYPE指针类型(结构体变量可能不存在,解引用出错)。
        ((TYPE *)0)->MEMBER  
                指针访问member元素
        &(((TYPE *)0)->MEMBER)
                获得member元素地址。由于整个结构体变量的首地址是0,所以元素地址大小为偏移量

container_of宏
        作用:已知结构体元素指针,得到结构体变量的指针
        原理:typeof得到member类型定义成一个指针,然后用这个指针减去该元素相对于整个结构体变量的偏移量(偏移量用offsetof宏得到的),减去之后得到的就是整个结构体变量的首地址了,再把这个地址强制类型转换为type *即可
        原型:
                #define container_of(ptr, type, member) ({      \
                const typeof(((type *)0)->member) * __mptr = (ptr);  \
                (type *)((char *)__mptr - offsetof(type, member)); })
                        ptr:数据结构成员指针
                        type:数据结构类型
                        member:  在数据结构中的成员

共用体
        结构体成员是独立存在,分布在不同的内存单元中
        共用体中成员不独立,共用内存单元
        union大小为内存最大元素大小。
        大小端模式:高字节对应高地址(大端模式),高字节对应低地址(小端模式 

枚举
        默认值从0增加,若定义了值,则从定义值增加
        宏定义和枚举的区别:枚举有关联符号封装,宏定义是离散的
        枚举用于有限集合(一周7天,一月31天,一年12个月) 

demo1: 

        结构体对齐

        

#include 

struct info
{
        int a;
        char b;
        short c;
};

struct info1
{
        int a;
        char b;
        short c;
}__attribute__((aligned(1024)));

struct info2
{
        int a;
        char b;
        short c;
}__attribute__((packed));

int main()
{
        struct  info n; 
        printf("sizeof(n) = %d\n",sizeof(n));    
        struct info1 n1;
        printf("sizeof(n1) = %ld\n",sizeof(n1));    
        struct info2 n2;
        printf("sizeof(n2) = %d\n",sizeof(n2));    
        printf("&n == %p\n",&n);    
        printf("n.a == %p\n",&(n.a));
        return 0;  
}

结果示例: 

C理解(三):结构体,共用体,枚举_第1张图片

demo2:

        offsetof宏和container_of宏

#include 

#define offsetof(TYPE, MEMBER) ((size_t)&((TYPE *)0)->MEMBER)

#define container_of(ptr, type, member) ({                      \
const typeof(((type *)0)->member) * __mptr = (ptr);     \
(type *)((char *)__mptr - offsetof(type, member)); })

struct info
{
        int a;
        char b;
        short c;
};

int main()
{
        struct info n;
        n.a = 1;
        n.b = 'c';
        n.c = 3;
        printf("&n == %p\n",&n);         
        printf("&(n.a) == %p\n",&(n.a));
        printf("member c offset : %ld\n",offsetof(struct info,c));
        printf("struct info head address: %p\n",container_of(&(n.c),struct info,c));
        struct info *p = container_of(&(n.c),struct info,c);
        printf("%d\n%c\n%d\n",p->a,p->b,p->c);
        return 0;
}

结果示例:

C理解(三):结构体,共用体,枚举_第2张图片

demo3:

        测试大小端 

#include 

union info
{
        int a;
        char b;
};

int main()
{
        union info n;
        n.a = 1;
        printf("%d\n",(int)n.b);
        if((int)n.b == 1)
        {
                printf("small mode\n");
        }
        else
        {
                printf("big mode\n");
        }
}

结果示例:

demo4:

         枚举

#include 
enum judge
{
        FALSE,
        TRUE
};
        enum judge func()
{
        enum judge  num;
        num = TRUE;
        return num;
}

int main()
{
        enum judge num = func();
        if(num = FALSE)
        {
                printf("FALSE\n");
        }
        else if(num = TRUE)
        {
                printf("TURE\n");
        }
        else
        {
                printf("union have no member\n");
        }
        printf("%d\n",TRUE);    //1
        printf("%d\n",FALSE);  //0
}

结果示例:

C理解(三):结构体,共用体,枚举_第3张图片

你可能感兴趣的:(c语言)