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;
}
通过这个整理,我对联合体,结构体,枚举类型,位段有了新的理解,初学如果有错误,欢迎大家指正。