6 结构体
约 3261 字大约 11 分钟
2025-04-05
结构体是一种构造数据类型 前面学过一种构造类型一一数
结构体是一种构造类型的数据结构,是一种或多种基本类型或构造类型的数据的集合。
构造类型: 不是基本类型的数据结构也不是指针类型,它是若干个相同或不同类型的数据构成的集合
描述一组具有相同类型数据的有序集合,用于处理大量相同类型的数据运算--数组
2、定义结构体类型
1、先定义结构体类型,再去定义结构体变量
struct 结构体类型名{
成员列表
}
struct stu{
int num;
char namer[20];
char sex;
}
//有了结构体类型后,就可以用类型定义变量了
struct stu lucy,bob,lilei;//定义了三个 struct stu 类型的变量每个变量都有三个成员,分别是 num name sex
结构体变量的大小是它所有成员之和
2、在定义结构体类型的时候顺便定义结构体变量,以后还可以定义结构体变量
struct 结构体类型名{
成员列表;
}结构体变量 1,变量2;
struct 结构体类型名 变量3,变量4;
struct stu{
int num;
char name[20];
char sex;
}lucy,bob,lilei;
struct stu xiaohong,xiaoming;
3.在定义结构体类型的时候,没有结构体类型名,顺便定义结构体变量
因为没有类型名,所以以后不能再定义相关类型的数据了
struct{
成员列表;
}变量 1,变量 2;
struct {
int num;
char name[20];
char sex;
}lucy,bob;
3、通常将一个结构体类型重新起个类型名,用新的类型名替代原先的类型
typedef struct stu {
int num;
char name[20];
char sex;
}STU;
以后 STU 就相当干 struct stu
1、结构体变量的定义和初始化
变量是若干个相同或不同数据构成的集合
在定义结构体变量之前首先得有结构体类型,然后再定义变量 在定义结构体变量的时候,可以顺便给结构体变量赋初值,被称为结构体的初始化 结构体变量初始化的时候,必须按各个成员顺序初始化
struct stu{
int num;
char name[20];
char sex;
};
struct stu boy;
struct stu lucy={
101,
"lucy",
'f'
};
2、结构体变量的使用
结构体变量成员的引用方法: 结构体变量.成员名
struct stu{
int num;
char name[20];
char sex;
};
struct stu bob;
bob.num=101;//bob 是个结构体变量,但是 bob.num 是个 int 类型的变量
bob.name 是个字符数组,是个字符数组的名字,代表字符数组的地址,是个常量
bob.name ="bob"://是不可行,是个常量
strcpy(bob.name,"bob");
print("%s\n",bob.name);
3、结构体成员多级引用
struct date{
int year;
int month;
int day;
};
struct stu{
int num;
char name[20];
char sex;
struct date birthday;
};
struct stu boy ={
101,
"lucy",
'f'
};
boy.birthday.yea r= 2000;
boy.birthday.month = 3;
boy.birthday.day = 1;
结构体变量相互赋值
struct stu{
int num;
char name[20];
char sex;
};
int main(int argc, char *argv[]){
struct stu bob=(101,"bob",'m');
struct stu lilei;
lilei=bob;
printf("%d %s %c\n",lilei.num,lilei.name,lilei.sex);
return 0;
}
必须是相同的结构体变量才能相互赋值
结构体数组
结构体数组是个数组,由若干个相同类型的结构体变量构成的集合
1、结构体数组的定义方法
struct 结构体类型名 数组名[元素个数];
struct stu{
int num;
char name[20];
char sex;
};
struct stu edu[3];//定义了一个 struct stu :类型的结构体数组 edu
2、结构体数组元素的引用
数组名[下标]
3、数组元素的使用
edu[0].num =101;//用 101 给 edu 数组的第0个结构体变量的 num 赋值strcpy(edu[1].name,"lucy");
结构体指针
即结构体的地址,结构体变量存放内存中也有起始地址 定义一个变量来存放这个地址,这个变量就是结构体指针变量。 结构体指针变量也是个指针,在 32 位环境下,指针变量的占4 个字节,存放一个地址
定义方法
struct 结构体类型名 * 结构体指针变量名;
struct stu{
int num;
char name[20];
};
struct stu *p;//定义了一个struct stu *类型的指针变量
struct stu boy;
p=&boy;
访问结构体变量的成员方法
boy.num=101;//可以,通过 结构体变量名.成员名
(*p).num=101;//可以,*p 相当于 p 指向的变量boy
p->num=101;//可以,指针->成员名
通过结构体指针来引用指针指向的结构体的成员,前提是指针必须先指向一个结构体变量。
应用场景
1、保存结构体变量的地址
typedef struct stu{
int num;
char name[20];
float score;
}STU;
int main(){
STU *p,lucy;
p=&lucy;
p->num=101;
strcpy(p->name,"baby");
//p->name="baby”://错误,因为 p->name 相当于lucy.name 是个字符数组的名字是个常量不能用等号赋值
}
2、传结构体变量的地址
void fun(STU*p){
p->num=101;
(*p).score=87.6:
strcpy(p->name,"lucy");
};
int main(){
STU girl;
fun(&girl);
printf("%d %s %fn",girl.num,girl.name,girl.score);
return 0;
}
3、传结构体数组的地址
结构体数组,是由若干个相同类型的结构体变量构成的集合。存放在内存里,也有起始地址,其实就是第 0 个结构体 的地址。
注意
结构体变量的地址编号和结构体第一个成员的地址编号相同,但指针类型不同
结构体数组的地址就是结构体数组中第0个元素的地址
typedef struct stu{
int num;
char name[20];
float score;
}STU;
int main{
STU boy;
printf("&boy-%pin"&boy);//STU *
printf(&(boy.num)=%p\n", &(boy.num));//int *
STU edu[3];
printf("edu=%p\n", edu);//STU *
printf(&edu[0]=%p\n", &edu[o]);//STU *
printf(&(edu[o].num)=%p\n",&(edu[o].num));//int *
return 0;
}
结构体内存分配
结构体变量大小是它所有成员的大小之和
struct stu{
int num;
int age;
}boy;
struct stu1{
char sex;
int age;
}lucy;
int main(){
printf("%d\n",sizeof(boy));//结果为 8
printf("sizeof(lucy)=%d\n",sizeof(lucy));//预期结果为5=1+4,实际结果为
printf(&lucy=%p\n" &lucy);//第一个成员的地址
printf("&(lucy.sex)=%p\n", &(lucy.sex));//第一个成员的地址
printf("&(lucy.age)=%p\n",&(lucy.age));//与第一个成员的地址编号差4
return 0;
}
给结构体变量分配内存的时候是有规则的 例子中的第一个元素的地址中间有三个字节空间没用,为了提高存取数据的速度32平台是4字节寻址的,如果挨着存可能要取两次才能取到数据,如果四字节四字节存一次就能取出,能够提高存取数据的速度
规则
规则1、以多少个字节为单位开辟内存
给结构体变量分配内存的时候,会去结构体变量中找基本类型的成员中哪个基本类型的成员占字节数多,就以它大大小为单位开辟内存
在 gcc中出现了 double 类型的例外
(1)成员中只有 char 型数据 ,以1字节为单位开辟内存。 (2)成员中出现了 short int 类型数据,没有更大字节数的基本类型数据以 2 字节为单位开辟内存 (3)出现了 int float 没有更大字节的基本类型数据的时候以 4 字节为单位开内存 (4)出现了 double 类型的数据 情况 1: 在 vc6.0 和 Visual Studio 中里,以8 字节为单位开辟内存。 情况 2: 在 Linux 环境 gcc.里,以4 字节为单位开辟内存 无论是那种环境,double 型变量,占8 字节(linux)开辟两次四字节
如果在结构体中出现了数组,数组可以看成多个变量的集合。如果出现指针的话,没有占字节数更大的类型的,以4 字节为单位开辟内存 在内存中存储结构体成员的时候,按定义的结构体成员的顺序存储。
规则 2:字节对齐
(1) char 1 字节对齐 ,即存放 char 型的变量,内存单元的编号是 1的倍数即可。 (2) short int2 字节对齐 ,即存放 short int 型的变量,起始内存单元的编号是 2 的倍数即可。 (3) int4 字节对齐 ,即存放 int 型的变量,起始内存单元的编号是 4 的倍数即可 (4) long int 在 32 位平台下,4 字节对齐 ,即存放long int 型的变量,起始内存单元的编号是4的倍数即可 (5) float 4 字节对齐 ,即存放 float 型的变量,起始内存单元的编号是 4 的倍数即可(6) double a.vc6.0 和Visual Studio 环境下 8 字节对齐,即存放 double 型变量的起始地址,必须是 8 的倍数,double 变量占8 字节 b.gcc 环境下
4 字节对齐,即存放 double 型变量的起始地址,必须是 4 的倍数,double 变量占8 字节。
当结构体成员中出现数组的时候,可以看成多个变量 开辟内存的时候,从上向下依次按成员在结构体中的位置顺序开辟空间
为什么要有字节对齐
用空间来换时间,提高 cpu 读取数据的效率
指定对齐原则:
使用#pragma pack改变默认对齐原则格式:
#pragma pack (value)时的指定对齐值value。
value只能是 1 2 4 8等 结构体成员中,占字节数最大的类型长度和value比较取较小值,为单位开辟内存
位段
在结构体中,以位为单位的成员,咱们称之为位段(位域)。
struct stu{
unsigned int a:2;
unsigned int b:6;
unsigned int c:4;
unsigned int d:4;
unsigned int i;
}data;
data所占内存 不能对位段成员取地址,因为位段成员可能不够一个字节
共用体
概念
在进行某些算法的时候,需要使几种不同类型的变量存到同一段内存单元中,几个变量所使用空间相互重叠 这种几个不同的变量共同占用一段内存的结构,在C语言中,被称作“共用体”类型结构
共用体和结构体类似,也是一种构造类型的数据结构 定义共用体类型的方法和结构体非常相似,把 stuct 改成union 就可以了。
共用体所有成员占有同一段地址空间 共用体的大小是其占内存长度最大的成员的大小 共用体的各个成员占用同一块内存。
特点
同一内存段可以用来存放几种不同类型的成员,但每一瞬时只有一种起作用 共用体变量中起作用的成员是最后一次存放的成员,在存入一个新的成员后原有的成员的值会被覆盖 共用体变量的地址和它的各成员的地址都是同一地址 共用体变量的初始化union data a={123};初始化共用体只能为第一个成员赋值,不能给所有成员都赋初值
枚举
将变量的值一一列举出来,变量的值只限于列举出来的值的范围内 枚举类型也是个构造类型的,类型定义类似结构体类型的定义使用枚举的时候,得先定义枚举类型,再定义枚举变量
定义方法
enum 枚举类型名{
枚举值列表;
};
在枚举值表中应列出所有可用值,也称为枚举元素枚举元素是常量,默认是从 0 开始编号的。
枚举变量仅能取枚举值所列元素
//定义枚举类型 week
enum week{//枚举类型
mon , tue , wed , thu , fri , sat,sun
};
enum week workday,weekday;//枚举变量workday 与 weekday 只能取 sun....sat 中的一个
workday = mon;//正确 weekday = tue;//正确 workday =abc; //错误,枚举值中没有 abc
枚举值是常量不能在程序中用赋值语句再对它赋值例如: sun-5;mon=2; sun-mon; 都是错误的 枚举元素本身由系统定义了一个表示序号的数值默认是从0开始顺序定义为0,1,2…… 如在week中,mon值为0,tue值为1,…… ,sun值为6
可以改变枚举值的默认值: 如enum week//枚举类型
enum week{
mon=3, tue, wed, thu, fri=4, sat,sun
};
mon=3,tue=4,以此类推fri=4 以此类推 在定义枚举类型的时候枚举元素可以用等号给它赋值,用来代表元素从几开始编号 在程序中,不能再次对枚举元素赋值,因为枚举元素是常量。
贡献者
版权所有
版权归属:PinkDopeyBug