自定义类型部分知识理解

1:结构体

结构体:一些值得集合,这些值是它的但结构体各个成员可能具有不同的类型。

结构变量属于标量类型,所以你可以像对待其他标量类型一样执行相同类型的操作。

结构体声明:

eg:

struct Stu

{

int a;

char b;

float c;

double d;

}

Stu称作标签,是和这些成员列表联系起来的,标签不是变量,但可以使用标签来创建变量;

eg:

struct  Stu x;

struct Stu y[10],*p;

你可以用标签创建结构体数组和结构体指针。

eg:

struct 

{

int a;

char b;

float c;

double d; 

}x,y[10],*p;

这种声明方式中,x,y[0],*p,都是变量,并且不要把结构体理解为数组,两个很不一样,数组中元素类型都是一样的,而结构体不一定都一样。

所以p = &x,这种表达式是非法的。

也可以用这种声明方式:

typedef struct 

{

charname[20];//名字
intage;//年龄
charsex[5];//性别
char id[20];//学号

}Stu;

用typedef创建一个新的类型,这样后面声明就可以这样声明了:

Stu x;

Stu y[10],*p;

j结构体成员也可以包含其他结构体;结构体成员的访问可以用(.)操作符来访问的

eg:

struct Stu x;
strcpy(x.name, "zhangsan");//使用.访问name成员
x.age = 20;//使用.访问age成员

结构体可以自引用吗,可以。你要这样用才行:
struct Stu
{
int a;
struct Stu* next;
};
其中没有struct和*都是不行的。
结构体的初始化:

struct Stu 

{

charname[20];//名字
intage;//年龄
charsex[5];//性别
char id[20];//学号

};

struct Stu x = {"lisan",20,"nan",100};//初始化

结构体内存对齐:




看到这种现象你就要了解结构体内存是怎么回事。

对其规则:

1. 第一个成员在与结构体变量偏移量为0的地址处。
2. 其他成员变量要对齐到某个数字(对齐数)的整数倍的地址处。
对齐数 = 编译器默认的一个对齐数与该成员大小的较小值。
VS中默认的值为8 
Linux中的默认值为4
3. 结构体总大小为最大对齐数(每个成员变量除了第一个成员都有一个对齐
数)的整数倍。
4. 如果嵌套了结构体的情况,嵌套的结构体对齐到自己的最大对齐数的整数倍处,结构体的整体大小就是所有最大对齐数(含嵌套结构的对齐数)的整数倍

eg:


总结:结构体内存对齐就是用空间换时间

位段:

位段的声明和任何普通的结构成员声明相同,但不同的是,位段声明为int,signed int ,或unsigned int类型。其次在成员名后面是一个冒号和一个整数。

这个整数是指定该位段所占用的位的数目。

eg:

structA
{
int_a:2;
int_b:5;
int_c:10;
int _d:30;
};

printf("%d",sizeof(struct A));值是8;

一个int 型有32位,前三个占17位,放_d三十位是很明显不够了,所以根据编译器可选择把_d放在下一个字节或者紧更着_c.

跟结构相比,位段可以达到同样的效果,但是可以很好的节省空间,但是有跨平台的问题存在。

为了节省空间尽可能的将奇数位放在一块。
枚举
枚举就是把可能的取值一一列举出来。

eg:


枚举成员变量不赋初值默认从0开始逐渐加1,也可以赋值


当GREEN赋值为4时,后面值就随前面值加1;

总结:枚举可以增加代码的可读性和可维护性,使用起来方便,可以定义多个常量

联合

联合中所有成员公用一块空间;

eg:


因为它公用一块内存空间,int为最大的4字节,所以联合变量的大小至少为最大成员的大小。

eg:

此时最大成员大小为2*7=14,14不是最大对齐数的整数倍,所以联合成员大小为16;