c语言自定义类型:结构体,位段,枚举,联合

结构体
结构体类型的创建(声明)

struct  student{
char name[1024];
int age;
};        //分号必须有
结构体是否可以自引用了?
这样对么?
struct student{
char name[1024];
int age;
struct student node;
};
答:这样是不对的,如果这样则结构体所占字节数就无法确定了.
正确自引用应该创建一个结构体指针,这样结构体大小就可以确定,如下
struct student{
char name[1024];
int age;
struct student* node;
};

结构体变量的定义和初始化

结构体变量的定义
struct student a;
 声明类型的同时,也定义了变量b
  struct  student{
char name[1024];
int age;
}a;        
我们发现这样定义变量很麻烦,可不可以直接用student来定义变量了?
可以的
在创建结构体的同时利用typedef即可实现,如下
typedef struct student{
char name[1024];
int age;
}student;       //之后就用此结构体来举例
结构体变量的初始化
定义变量的同时就可以初始化
student a={'小明',15};

结构体嵌套初始化
struct Node {    
int data;    
student p;    
struct Node* next;  
}n1 = {10, {4,5}, NULL};            

结构体大小的计算(结构体内存对齐规则)(默认32位系统下)

int  占4字节,char占1个字节,指针占4字节,那么结构体所占字节就是所有类型所占字节的总和吗?
不是的.
结构体大小,遵循结构体内存对齐规则,有四条如下
1. 第一个成员在与结构体变量偏移量为0的地址处。    //即起始位置0
2. 其他成员变量要对齐到某个数字(对齐数)的整数倍的地址处。
对齐数 = 编译器默认的一个对齐数 与 该成员大小的较小值
VS中默认的值为8 
Linux中没有默认值
3. 结构体总大小为最大对齐数(每个成员变量都有一个对齐数)的整数倍。 
4. 如果嵌套了结构体的情况,嵌套的结构体对齐到自己的最大对齐数的整数倍处,结构体的整体大小就是所有最大对齐数(含嵌套结构体的对齐数)的整数倍。
根据上述四条规则即可正确计算出结构体的大小.
如下结构体所占字节数?(默认vs下,假设起始地址为0)
struct S1 {    
char c1;    //1个字节,地址0
int i;          //4个字节,8大于4,所以对齐数为4,所以i地址为从4开始,占4,5,6,7四个字节
char c2;    //1个字节,1<8,所以对齐数为1,所以占地址8一个字节
                //所以4+4+1=9,又因为9不是该结构体最大对齐数4的整数倍,所以该结构体占12字节
}; 
printf("%d\n", sizeof(struct S1));         //12
结构体内存对齐的优点:其虽然浪费了内存,但却换来了硬件上的方便,提高了内存访问效率
到这里可能就会有人想到,如果合理的安排结构体成员的顺序,在一定程度上是可以节省内存的
但是试想,如果只为了节省空间而将成员的顺序打乱了,代码的可读性将有可能大大降低,所以如何
排放结构体成员还是以代码可读性为优先前提较好,毕竟当前计算机内存足够使用

默认对齐数的修改(当默认对齐数不合适的时候我们可以自己修改)
在结构体之前加上
#pragma pack(8)    //设置默认对齐数为8
结构体之后加上
#pragma pack()//还原默认对齐数  

位段

有些情况如性别,只有男女两种情况,这是有一位二进制bit位(1或0)就足以表示,位段就可以实现
c语言在创建结构体的时候可以指定成员所占的二进制位数(bit),即为位段,位段成员名后有一个冒号和数字,
数字即为指定所占的二进制bit位,例如
struct A {    
int _a:2;             //    占2位(bit)
int _b:5;    
int _c:10;    
int _d:30; 
};
位段的内存分配 
1.  位段的成员可以是 int unsigned int signed int 或者是 char (属于整形家族)类型 
2.  位段的空间上是按照需要以4个字节( int )或者1个字节( char )的方式来开辟的。 
3.  位段涉及很多不确定因素,位段是不跨平台的,注重可移植的程序应该避免使用位段。

枚举

枚举就是一一列举
例如一周有七天可以一一列举
enum day{
 Mon,    //默认从0开始,一次递增1,当然在定义的时候也可以赋初值。 
 Tues,    
 Wed,    
 Thur,    
 Fri,    
 Sat,    
 Sun
 };         //这就是枚举类型的定义
 枚举的优点:
1. 增加代码的可读性和可维护性 
 2. 和#define定义的标识符比较枚举有类型检查,更加严谨。 
 3. 防止了命名污染(封装) 
 4. 便于调试 
 5. 使用方便,一次可以定义多个常量

联合(共用体)

联合体的特点:成员共用内存空间(所以它的大小至少为它的成员的最大值)
联合体的定义
union  un{
int a;
char arr[10];
};
联合变量的定义
union  un  un1;
联合大小的计算 
联合的大小至少是最大成员的大小。 
当最大成员大小不是最大对齐数的整数倍的时候,就要对齐到最大对齐数的整数倍。

你可能感兴趣的:(c,or,c++)