目录
结构体介绍
C语言是一门面向功能的的开发语言,没有面向对象的概念,但是C语言提供了结构体来描述复杂对象,结构体并不属于内置类型,需要使用者自己建立结构声明(也被称作模板)。
提示:以下是本篇文章正文内容,下面案例可供参考
一、建立结构声明
结构声明的一般形式(也被称作模板):
struct 结构名{
成员列表
};
具体结构声明
struct book{
char name[20];
int age;
};
首先是关键字struct,它表明跟在其后的是一个结构,后面是一个可选的结构名,在代码块中的是结构成员列表,每个成员都用自己的声明来描述,成员可以是任意的一种C的数据结构也可以是其他结构,结尾的分号是必须的它表示结构布局结束,把结构声明在何处表示了该结构体的储存类别,结构声明在函数内,就是一个具有自动存储期、块作用域且无连接的模板,在函数外声明时,就是一个静态存储期、文件作用域、外部链接的模板。
结构体是一种数据类型,是创建变量的模板,不占用内存空间;结构体变量才包含了实实在在的数据、需要存储空间;
特殊结构声明(省略结构名的匿名机构声明)
struct{ //省略模板(结构体类型)名称的特殊声明
char book[20];
int age;
};
省略结构名的结构声明,无法用模板(结构体类型)创建变量,只能在结构声明时创建结构体变量。
二、结构变量的定义和初始化
在结构声明后,我们就可以通过模板来定义一个结构体变量,可以在结构声明时创创建或者在模块作用域中使用模块(结构体类型)创建。
struct book{ //在结构声明时定义变量
char book[20];
int age;
}s1,s2;
struct book s3; //在结构声明的作用域中使用模板定义变量
在定义一个变量后我们就要对它初始化,结构体变量的初始化,结构体变量的初始化又以下几种方式:
struct book{
char name[20];
int age;
}s1,s2={"laozi",20}; //在声明定义的同时初始化
int main() {
struct book gg={"jianai",20}; //使用模板定义变量的时初始化
gg.age = 20;
gg.name[gg.age] = "gg"; //更改结构体变量成员内容
}
三、结构体的内存对齐
了解了结构体的使用方法,还有一个问题结构体作为自定义类型,他在内存的开辟空间时多少呢,每个成员占用多少内存空间。
struct book{
char name;
int age;
char str;
}s1,s2={'a',20,'b'};
int main() {
printf("%zd",sizeof(s2));
}
两个char的占用两个字节,一个int占用四个字节,拿s2的大小总共是六个字节,但实际sizeof计算s2的大小却是12个字节???
这里就要提到结构体的内存对齐规制了:
为什么存在内存对齐?
1. 平台原因(移植原因): 不是所有的硬件平台都能访问任意地址上的任意数据的;某些硬件平台只能在某些地址处取某些特 定类型的数据,否则抛出硬件异常。
2. 性能原因: 数据结构(尤其是栈)应该尽可能地在自然边界上对齐。 原因在于,为了访问未对齐的内存,处理器需要作两次内存访问;而对齐的内存访问仅需要一次访 问。
四、修改默认对齐数
#pragma 这个预处理指令,这里我们再次使用,可以改变我们的默认对齐数。
#pragma pack(1) //设置默认对起数为1
struct book{
char name;
int age;
char str;
}s1={'a',20,'b'};
#pragma pack() //在定义结构体变量后还原默认对起数
int main() {
printf("%zd\n",sizeof(s1));
}
我们在修改默认对齐数为1是,所有成员的对齐数都为1,成员偏移量可以是任何数,所以1+4+1=6个字节的大小。
五、结构体传参
struct book{
char name;
int age;
char str;
}s1={'a',20,'b'};
void gg_1(struct book s) {
printf("%c %d %c", s.name, s.age, s.str);
}
void gg_2(struct book* s) {
printf("%c %d %c", s->name, s->age, s->str);
}
int main() {
gg_1(s1);
gg_2(&s1);
}
这里我们封装了两个打印结构体成员内容的函数,一个是传值,一个是传址,以上两个函数均能实现目的,那么他们的区别在哪里呢?
函数传参的时候,参数是需要压栈,会有时间和空间上的系统开销。 如果传递一个结构体对象的时候,结构体过大,参数压栈的的系统开销比较大,所以会导致性能的下降,所以相较于传值,传址的速度和占用空间都要跟优。