1.C语言构造类型
构造数据类型:是根据已定义的一个或多个数据类型用构造的方法来定义的。也就是说,一个构造类型的值可以分解成若干个“成员”或“元素”。每个“成员”都是一个基本数据类型或又是一个构造类型
在C语言中,构造类型有以下几种
数组类型
结构体类型
共用体(联合)类型
2.什么是结构体
在实际问题中,一组数据往往具有不同的数据类型,例如,在学生登记表中,姓名应为字符型,学号可以为整型或字符型,年龄为整型,性别位字符型,成绩位整型或实型。显然不能用一个数组来存放这一组数据。因为数组中各元素的类型和长度都必须一致。以便于编译系统处理。为了解决这个问题。C语言中给出了另一种构造数据类型--结构或叫结构体。它相当于其他高级语言中的记录
"结构"是一种构造类型,它使由若干“成员”组成的,每一个成员可以是一个基本数据类型或又是一个构造类型。结构既是一种“构造”而成的数据类型,那么在说明和使用之前必须先定义它,也就是构造它。如同在说明和调用函数之前要先定义函数一样。
3、为什么要由结构类型?
结构体可以把功能相同的数据组织起来,灿在一汽,用的时候方便,而且在函数调用时,若传递若干个数据是很不方便的,但是用结构体把这些数据组织起来的话,直接传递一个结构体就行了。
4、定义结构体的方法
定义一个结构的一般形式为:
struct 结构名{
成员列表;
};
【注意】结构体定义完成后并没有分配空间
例如
//定义一个结构体
struct Student{
int schoolId;
char name[20];
int age;
float score;
};//注意,此处的分号必须有
5.结构变量中成员的访问方法
一般形式:
结构变量名.成员变量
例如:
//1.定以后再初始化
//用结构体定义变量
struct Student st;
//用.来访问结构体变量的成员
st.schoolId = 1;
strcpy(st.name, "Amos");
st.age = 24;
st.score = 90.5f;
//2、定义的时候初始化
struct Student st2 = {2,"Allen",22,90.0f};
printf("第一个学生 schoolId:%d, name: %s, age:%d, score:%0.2f\n",st.schoolId,st.name,st.age,st.score);
printf("第二个学生 schoolId:%d, name: %s, age:%d, score:%0.2f\n",st2.schoolId,st2.name,st2.age,st2.score);
打印结果:
第一个学生 schoolId:1, name: Amos, age:24, score:90.50
第二个学生 schoolId:2, name: Allen, age:22, score:90.00
6.存储原理
内存是以字节位单位编号的,但一些硬件平台对某些特定类型的数据只能从某些特定的地址开始,比如从偶地址开始,若不按照适合其平台的要求对数据存放进行对其,会影响效率。因此,在内存中,各类型的数据是按照一定的规则在内存中存放的。这就是对齐问题。
结构体占用的内存空间是每个成员占用的字节数之和(考虑对齐问题)。
7、结构体数据成员对齐的意义
许多实际的计算机系统对基本类型数据在内存中存放的位置有限制,他们会要求这些数据的起始地址的值是某个数k的倍数,这就是所谓的内存对齐,而这个k则被称为该数据类型的对齐模数
这种强制要求一来简化了处理器与内存之间的传输系统的设计,而来可以提升读取数据的速度。比如这么一种处理器,它每次读取内存的时候都从某个8倍数的地址开始,一次读出或写入8个自己的数据,加入软件能保证double类型的数据都从8倍数地址开始,那么读或写一个double类型数据就只需依次内存操作。否则,我们就可以能需要两次内存操作才能完成这个动作,因为数据获取敲好横跨在两个符合对齐要求的字节内存块上。
8、结构体变量占用存储空间大小
8.1 结构体大小的计算方法和步骤 |
|
1)将结构体内所有数据成员的长度相加,记为sum_a
2 )将个数据成员为了内存对齐,按照各自对齐模数而填充的字节数累加到sum_a上,记为sum_b。对齐模数是#pragma pack指定的数值,以及该数据成员自身长度中数值较小者。该数据相对起始位置应该是对齐模数的整数倍。
3)将sum_b向结构体模数对齐,对齐模数是#pragma pac指定的数值和结构体内部最大的基本数据类型成员长度中数值较小者,以及该数据成员自身长度中数值较小者。结构体长度应该是对齐模数的整数倍。
对齐模数:【一般就是结构体内部最大的基本数据类型成员长度】
所谓对齐在N 上就是值指:“存放起始地址%N = 0”
例如:
//定义结构体
struct Student{
int schoolId;//4
char name[20];//20 ---> 刚好是模数4的倍数,所以分配20个字节就好
char sex;//1 ---> 因为模数是4,不够的话补齐
int age;//4
float score;//4
};
//用结构体定义变量
struct Student st;
printf("size %ld", sizeof(st));
打印结果;
size 36
分析结果:
不是想象中的4+20+1+4+4= 33,而是36
因为该结构体中占用字节数对大的是4,因此模数是4
所以应该用 4+20+4+4+4= 36 来计算
9.结构体的作用域
在函数外定义的是全局结构体,作用域从定义位置开始直到文件结束
在函数内定义的是局部结构体,作用域是从定义位置开始直到函数结束