结构体
结构体是一个用的最广的自定义类型其可以表示如下
struct TEST{
char a;
short b;
int c;
double d;
};
但是需要注意的是不能包含自己类型的结构体变量,但是可以包含自己类型的结构体指针如下
struct TEST{
char a;
short b;
int c;
double d;
//struct TEST s;不能包含自己类型的结构体变量
struct TEST *s;//可以包含自己类型的结构体指针
};
因为自定义类型中不能包含自己结构体的这个变量,因为对于这个结构体的大小是要声明完之后才能得出,而在声明中再定义一个结构体,因为这个结构体的大小不知道,故会编译失败
当然,我们知道结构体也是可以赋值的可以在初始化的时候赋值,也可以自行赋值,比如
struct TEST{
char a[10];
short b;
int c;
double d;
};
int main()
{
struct TEST S;
S.b=1;
//S.a="123";切记,结构体中char不能这样赋值,要通过strcpy函数来赋值
strcpy(S.a,"123");
S.c=2;
S.d=3.14;
}
出自之外,结构体可以使用{}初始化但不能赋值,比如可以写成如下形式
struct TEST{
char a[10];
short b;
int c;
double d;
};
int main()
{
struct TEST S={"123",1,2,3.14};
//S={"234",5,6,12.8};这样的赋值是不行的
//应该这样赋值
struct TEST S={"123",1,2,3.14};
struct TEST S1={"234",5,6,12.8};
S=S1;
}
重点 结构体的内存对齐
结构体中的成员和成员不一定在连续的内存空间上的
结构体内存对其规则如下:
1.第一个成员在与结构体变量偏移量为0的地址处
2.其他成员变量要对齐某个数字(对齐数)的整数倍的地址处
对齐数=编译器默认的一个对齐数与该成员大小的较小值
**·**vs中默认值为8
3.结构体总大小为最大对齐数的整数倍(每个成员变量都有一个对齐数)的整数倍。
4如果嵌套了结构体的情况,嵌套的结构体对齐到自己的最大对齐数的整数倍处,结构体的整体大小就是所有最大对齐数(含嵌套结构体的对齐数)的整数倍。
那么为什么要内存对齐呢
1.平台原因
不是所有的硬件平台都能访问任意地址上的任意数据的;某些硬件平台只能在某些地址处取某些特定类型的数据,否则抛出硬件异常
2.性能原因
数据结构应尽可能的自然边界上对齐,对齐的内存仅需访问一次能存即可。
例如求如下结构体的内存大小
struct TEST{
char a;
int c;
};
很多初学者认为应该是5字节,a占1个字节,c占4个字节。但是通过内存对齐我们知道,a占1个字节是没错,但是c是4个字节,如果存在地址为2的地方,并不是4的整数倍(默认系统对齐数为8),所以需要浪费3个字节,存到地址为5的地方,故大小应为8。
红色标记为浪费的内存。
再比如
struct TEST{
char a;
double b;
int c;
char d;
};
首先,a是1个字节,但是b占8个字节,所以其需要存到地址为9的地址上,浪费7个字节。c占4个字节,16刚好为4的倍数,故其存到地址为17的位置上,而d占1字节,故存到地址为21的位置上,而根据内存对齐规则我们知道,结构体总大小为最大对齐数的整数倍,故该结构体大小为24。
除此外 #pragma pack() 语句是最大对齐数修改,即可以自行改变系统默认的最大对齐数。
枚举
所谓枚举类型,就是用一组数量有限的标识符来表示一组连续的整型常数,使能够更清晰的表示出现实世界
其样式如下
enum TEST{
man,
woman,
unkonw,
};
我们知道man对应的是0,woman对应的是1,unkonw对应的是2。值得注意的是在C语言中枚举和int是等价的,而C++中枚举和int是完全不相同的两种类型,不能混淆使用。
我们看一个关于枚举的面试题
enum TEST{
man,
woman=10,
unkonw,
};
int main()
{
enum TEST a=man;
enum TEST b=unkonw;
printf("%d %d\n",a,b);
return 0;
}
我们知道,当在枚举中不赋值,则默认从0开始增加,而题中woman赋值为10,故unkonw变为11。所以打印结果为0 11。
联合体
在进行某些算法的C语言编程的时候,需要使几种不同类型的变量存放到同一段内存单元中。也就是使用覆盖技术,几个变量互相覆盖。这种几个不同的变量共同占用一段内存的结构,在C语言中,被称作"共用体"类型结构,简称共用体,也叫联合体。
其样式如下
union TSET{
int a;
int b;
char c;
};
我们知道,联合体成员共用同一个内存,各种成员共用同一个内存空间,会导致修改一个成员就影响到其他成员的内容。而联合体这样的语法除了c,c++之外大部分编程语言都没有,整体上来看联合体没啥用。但是有些场景下,联合体可以给我们带来方便如果某个内存空间可以按照多种方式来理解的话,就比较适合用联合体。
除此之外,也可以用结构体来判断该机器是大端还是小端,如图
代码如下
union TEST{
int a;
char c;
};
int search()
{
union TEST s;
s.c=0x11223344;
if(s.a==0x44){
return 1;//大端返回1
}
return 0;//小端返回0
}
int main()
{
printf("%d\n",search());
return 0;
}