梓益C语言学习笔记之结构体-共用体-枚举
有人说,我们需要将不同类型的数据组合成一个整体,于是,就有了结构体
一、结构体的概念:
一种或多种基本类型或构造类型的数据的集合。
二、定义方法:
先定义结构体类型,再去定义结构体变量
struct 结构体类型名{
成员列表
};
如:
struct stu{
int num;
char name[20];
char sex;
};
struct stu lucy,bob,lilei;//定义了三个struct stu类型的变量
每个变量都有三个成员,分别是num name sex
通常咱们将一个结构体类型重新起个类型名,用新的类型名替代原先的类型
**最常用的定义结构体的方法是:
typedef struct stu{
int num;
char name[20];
char sex;
}STU;
STU lucy;
三、初始化及使用:
typedef struct stu{
int num;
char name[20];
char sex;
}STU;
STU lucy={101,"lucy",'f'};
STU bob;
bob.num=101;//bob是个结构体变量,但是bob.num是个int 类型的变量
bob.name 是个字符数组,是个字符数组的名字,代表字符数组的地址,是个常量
bob.name ="bob";//是不可行,是个常量
strcpy(bob.name,"bob");
四、结构体数组
结构体数组是个数组,由若干个相同类型的结构体变量构成的集合
1、结构体数组的定义方法:
struct stu{
int num;
char name[20];
char sex;
};
struct stu edu[3];//定义了一个struct stu 类型的结构体数组edu,
这个数组有3个元素分别是edu[0] 、edu[1]、edu[2]
可以这样赋值:STU edu[3]={
{101,"Lucy",78},
{102,"Bob",59.5},
{103,"Tom",85}
};
2、数组元素的使用
edu[0].num =101;//用101给edu数组的第0个结构体变量的num赋值
strcpy(edu[1].name,"lucy");
五、结构体指针
即结构体的地址,结构体变量存放内存中,也有起始地址
定义一个变量来存放这个地址,那这个变量就是结构体指针变量。
1、结构体指针变量的定义方法:
struct stu{
int num;
char name[20];
};
struct stu * p;//定义了一个struct stu *类型的指针变量,变量名是p,p占4个字节,用来保存结构体变量的地址编号
使用:struct stu boy;
p=&boy;
访问结构体变量的成员方法:
boy.num=101;//可以,通过结构体变量名.成员名
(*p).num=101;//可以,*p相当于p指向的变量boy
p->num=101;//可以,指针->成员名
通过结构体指针来引用指针指向的结构体的成员,前提是指针必须先指向一个结构体变量。
六、结构体内存分配
为什么要有字节对齐?
用空间来换时间,提高cpu读取数据的效率
结构体变量大小是所有成员之和
规则1:结构体分配内存时哪个基本类型的成员占字节数多,就以它的大小为单位开辟内存,
在gcc中出现了double类型的,例外
1:成员中只有char型数据 ,以1字节为单位开辟内存。
2:成员中出现了short int 没有更大字节数的基本类型数据以2字节为单位开辟内存
3、出现了int float 没有更大字节的基本类型数据的时候以4字节为单位开辟内存。
4、出现了double类型的数据
情况1:
在vc里,以8字节为单位开辟内存。
情况2:
在gcc里,以4字节为单位开辟内存。
无论是那种环境,double型变量,占8字节。
注意:
如果在结构体中出现了数组,数组可以看成多个变量的集合。
如果出现指针的话,没有占字节数更大的类型的,以4字节为单位开辟内存。
在内存中存储结构体成员的时候,按定义的结构体成员的顺序存储。
例1:struct stu{
char sex;
int age;
}lucy;
lucy的大小是4的倍数。
规则2:字节对齐
1:char 1字节对齐 ,即存放char型的变量,内存单元的编号是1的倍数即可。
2:short int 2字节对齐 ,即存放short int 型的变量,起始内存单元的编号是2的倍数即可。
3:int 4字节对齐 ,即存放int 型的变量,起始内存单元的编号是4的倍数即可
4:long int 在32位平台下,4字节对齐 ,即存放long int 型的变量,起始内存单元的编号是4的倍数即可
5:float 4字节对齐 ,即存放float 型的变量,起始内存单元的编号是4的倍数即可
6:double
1.vc环境下
8字节对齐,即存放double型变量的起始地址,必须是8的倍数,double变量占8字节
2.gcc环境下
4字节对齐,即存放double型变量的起始地址,必须是4的倍数,double变量占8字节。
注意3:当结构体成员中出现数组的时候,可以看成多个变量。
注意4:开辟内存的时候,从上向下依次按成员在结构体中的位置顺序开辟空间
例1:
struct stu{
char a;
short b;
int c;
}temp;
例3://temp 8个字节
#include
struct stu{
char a;
short int b;
int c;
}temp;
结果分析:
a的地址和b的地址差2个字节
b的地址和c的地址差2个字节
例4:temp的大小为12个字节
#include
struct stu{
char a;
int c;
short int b;
}temp;
结果分析:
a和c的地址差4个字节
c和b的地址差4个字节
例5:
struct stu{
char buf[10];
int a;
}temp;
//temp占 16个字节
例6:
struct stu{
char a;
double b;
}temp;
temp:
在vc中占 16个字节 a和b的地址差8个字节
在gcc中占 12个字节 a和b的地址差4个字节
#include
struct stu{
char a;
double b;
}temp;
指定对齐原则:
使用#pragma pack改变默认对其原则
#pragma pack (value)
1.value只能是:1 2 4 8等
2.指定对齐值与数据类型对齐值相比取较小值
说明:咱们制定一个value
1:以多少个字节为单位开辟内存
结构体成员中,占字节数最大的类型长度和value比较,
取较小值,为单位开辟内存
例7:
#pragma pack(2)
struct stu{
char a;
int b;
} ;
以2个字节为单位开辟内存
#include
#pragma pack(2)
struct stu{
char a;
int b;
}temp;
int main()
{
printf("%d\n",sizeof(temp));
printf("%p\n",&(temp.a));
printf("%p\n",&(temp.b));
return 0;
}
temp的大小为6个字节
a和b的地址差2个字节
如:如果指定对齐值:
设为1:则short、int、float等均为1
设为2:则char仍为1,short为2,int 变为2
七、位段
在结构体中,以位为单位的成员,咱们称之为位段(位域)。
struct packed_data{
unsigned int a:2;
unsigned int b:6;
unsigned int c:4;
unsigned int d:4;
unsigned int i;
} data;
对于位段成员的引用如下:
data.a =2
赋值时,不要超出位段定义的范围;
如段成员a定义为2位,最大值为3,即(11)2
所以data.a =5,就会取5的低两位进行赋值 101
八、共用体
**每次只能使用共用体的一个变量
几种不同类型的变量存到同一段内存单元中,几个变量所使用空间相互重叠
这种几个不同的变量共同占用一段内存的结构,在C语言中,被称作“共用体”类型结构
共用体所有成员占有同一段地址空间
共用体的大小是其占内存长度最大的成员的大小
typedef union data{
short int i;
char ch;
float f;
}DATA;
DATA temp2;
共用体temp2占4个字节,即i、ch、f共用4个字节
九、枚举
将变量的值一一列举出来,变量的值只限于列举出来的值的范围内
例:
定义枚举类型 week
enum week //枚举类型
{
mon,tue,wed,thu,fri,sat,sun
};
enum week workday,weekday;//枚举变量
workday与weekday只能取sun….sat中的一个