结构体、位段(位域)、联合体、枚举类型大小计算及分析

    技术2022-07-14  75

    1.结构体

    void test1() { typedef struct { int i; }s; typedef struct { char c1;//1 char c2;//1 int i;//4 }s1;//8 typedef struct { char c1;//1 int i;//4 char c2;//1 }s2;//12 typedef struct { char c2;//1 double d;//8 int i;//4 }s3;//24 typedef struct { char c1;//1 s s;//4 double i;//8 }s8;//16 typedef struct { char c1;//1 s1 s1;//8 int i;//4 }s4;//16 typedef struct { char c1;//1 s3 s3;//24 int i;//4 }s7;//40 /*typedef struct { char c1;//1 int i;//4 s3 s3;//24 }s7;//32*/ printf("s->%d\n", sizeof(s)); printf("s1->%d\n", sizeof(s1)); printf("s2->%d\n", sizeof(s2)); printf("s3->%d\n", sizeof(s3)); printf("s4->%d\n", sizeof(s4)); printf("s7->%d\n", sizeof(s7)); printf("s8->%d\n", sizeof(s8)); printf("char->%d\n", sizeof(char));//1 printf("short->%d\n", sizeof(short));//2 printf("int->%d\n", sizeof(int));//4 printf("long->%d\n", sizeof(long));//4 printf("char*->%d\n", sizeof(char*));//4 printf("double->%d\n", sizeof(double));//8 printf("long long->%d\n", sizeof(long long));//8 /*typedef struct node { int data; node* next;//必须加上struct,此时还没重命名 }node;*/ /*typedef struct node { int data; struct node* next; }node;*/ /*struct node { int data; struct node next;//不能直接包含自身,引发递归定义了/ };*/ /*typedef struct stu//(不声明时为匿名结构体) { int data; }s7;*///重命名 //s1 s2;//重命名 //struct stu s2; /* struct stu//(不声明时为匿名结构体) { int data; }s5;//定义一个自定义类型的变量 s5.data;*/ /*struct //(不声明时为匿名结构体) { int data; }s6; s6.data;*/ }

    1.结构体是一个自定义类型,内部数据类型独有内存空间,和联合体(共用体要做好区分)。

    2.计算机结构体大小需要内存对齐,为什么需要内存对齐呢? 由于32位处理器一次可以取出32个比特位(4字节),所以取数据的时候不是一个字节一个字节的取,如果数据类型小于4字节的话,会取出来然后分割,而且如果数据连续存储,就会更加麻烦,所以引入内存对齐,以空间换时间。 3.如何进行内存对齐? 默认对齐数(win 8,linux 4)#pragma pack(n) n=1 2 4 8 16 第一位默认0开始 之后的数据要对齐,对齐数=min(默认对齐数,当前数据大小) 结构体总大小为最大对齐数的整数倍。 嵌套了结构体的话(不能自引用,指针除外),总大小为最大对齐数的整数倍(max(结构体,数据类型)),详情留意s3 s4 s8,s7计算。

    2.位域

    void test2() { struct A { int _b : 5;//4 int _c : 4;//4 };//4 struct B { char _a : 3; char _b : 4;//1 char _c : 5;//2 int _d : 5;//4 };//8 struct C { char _a : 3; char _b : 4;//1 char _c1 : 5;//2 char _c2 : 5;//3 char _c3 : 5;//4 char _c4 : 5;//5 int _d : 5;//9 };//12 printf("%d\n",sizeof(struct A));//4 printf("%d\n", sizeof(struct B));//8 printf("%d\n", sizeof(struct C));//12 }

    位域是控制类型所占的比特位。(char 不能大于8,int不能大于32),小于该类型的比特位可以拼接。 也会存在内存对齐,对齐为最大类型的整数倍,参见B,C.

    3.联合体

    void test3() { union un1 { char c; int i; }u1; union un2 { char c[5]; int i; }u2; printf("%d\n", sizeof(u1));//4 printf("%d\n", sizeof(u2));//8 u1.i = 1; if (u1.c == 1) { printf("小端机\n"); } else { printf("大端机\n"); } printf("%d\n", sizeof(u1)); }

    联合体成员共用一块内存,大小为最大数据类型,适用于不常同时出现的数据,有利于节省内存空间。 我们可以通过赋值来验证这个,同时可以通过这个方法,来验证大小端。 同时联合体也会内存对齐,u2的最大为5,但是最大对齐数为4,所以要对齐为8.

    4.枚举类型

    void test4() { enum day { HOUR, MINUTE,//递推 SECOND=5,//可以给数据大小 }; printf("%d\n", HOUR); printf("%d\n", MINUTE); printf("%d\n", SECOND); }

    枚举类型常量,和宏的区别 1.可读性好。 2.有类型检查,安全,便于调试。 3.封装性好,防止命名污染。 4.使用方便,可以一次定义好几个,同时递推数据大小,默认从0开始,也可以自己给值。

    int main() { //test1();//结构体 //test2();//位段(位域) //test3();//联合体共用内存空间,大小为数据类型大的所占的空间。 //test4();//枚举常量 system("pause"); return 0; }

    通过这个整理,我对联合体,结构体,枚举类型,位段有了新的理解,初学如果有错误,欢迎大家指正。

    Processed: 0.016, SQL: 9