黑马程序员——C语言基础---结构体2
2015-09-29 18:06
489 查看
------Java培训、Android培训、iOS培训、.Net培训、期待与您交流! ------
五、结构体变量存储原理
1、结构体存储原理
结构名只能表示一个结构形式,编译系统并不对它分配内存空间。只有当某变量被说明为这
种类型的结构时,才对该变量分配存储空间。
内存是以字节为单位编号,但一些硬件平台对某些特定类型的数据只能从某些特定地址开始, 比如从偶地址开始。若不按照适合其平台的要求对数据存放进行对齐,会影响到效率。 因此,在内存中,各类型的数据是按照一定的规则在内存中存放的,这就是对齐问题。
结构体占用的内存空间是每个成员占用的字节数之和(考虑对齐问题)。
2、结构体数据成员对齐的意义
许多实际的计算机系统对基本类型数据在内存中存放的位置有限制,它们会要求这些数据的起始 地址的值是某个数k的倍数,这就是所谓的内存对齐,而这个k则被称为该数据类型的对齐模数 (alignment modulus)。
这种强制的要求一来简化了处理器与内存之间传输系统的设计,二来可以提升读取数据的速度。 比如这么一种处理器,它每次读写内存的时候都从某个8倍数的地址开始,一次读出或写入8个字 节的数据,假如软件能保证double类型的数据都从8倍数地址开始,那么读或写一个double类型数 据就只需要一次内存操作。否则,我们就可能需要两次内存操作才能完成这个动作,因为数据或 许恰好横跨在两个符合对齐要求的8字节内存块上。
3、结构体对齐的含义
1)结构体总长度
2)结构体内各数据成员的内存对齐,即该数据成员相对结构体的起始位置
六、结构体作用域
1、作用域概述
结构类型定义在函数内部的作用域与局部变量的作用域是相同的
函数外部定义的结构体类型类似全局变量
全局作用域:从定义的那一行开始直到本文件结束为止
2、作用域分类
结构体根据作用于可以分为全局结构体、局部结构体
七、结构体数组概念及定义
1、结构数组概念
数组的元素也可以是结构类型的。因此可以构成结构型数组。结构数组的每一个元素都是具 有相同结构类型的下标结构变量。在实际应用中,经常用结构数组来表示具有相同数据结构的一 个群体。如一个班的学生档案,一个车间职工的工资表等。
2、结构数组定义
定义格式:
struct 结构名
{
成员表列
}数组名[数组长度];
结构体数组定义:
结构体数组定义的第一种方式:
1)定义结构体的同时,定义数组
struct Student
{
int age;
char *name;
int s_no;
float score;
}stu[5];
2)先定义结构体,后定义数组
struct Student boy[5];
例如:定义一个长度为5的数组,其中每一个元素都是 stu结构类型
struct stu
{
int num;
char *name;
char sex;
float score;
}boy[5];
定义了一个结构数组boy,共有5个元素,boy[0]~boy[4]。每个数组元素都具有struct stu的结 构形式。
八、结构体数组初始化
1、结构数组的初始化
//1、定义结构体数组的时候,进行初始化
struct Student{
char name[20];
int age;
}boys[3]={{"sb",18},{"zbz",38},{"cgx",28}};
//2、定义的同时进行初始化
struct Student girls[2]={{"fengjie",18},{"cjk",28}};
//3、先定义后初始化,整体赋值
struct Student ds[2];
ds[0]=(struct Student){"xzmly",18};
ds[1]=(struct Student){"bdjy",18};
//4、先定义结构体数组,后初始化
struct Student stu[2];
//stu[0].name = "zhangsan";
//strcpy(stu[0].name,"zhangsan");
scanf("%s",stu[0].name);
2、结构数组遍历
struct Student{
char name[20];
int age;
}boys[3]={{"sb",18},{"zbz",38},{"cgx",28}};
for(int i=0;i<3;i++){
printf("name:%s,age:%d\n",boys[i].name,boys[i].age);
}
九、结构指针定义和初始化
1、指向结构体变量的指针
一个指针变量当用来指向一个结构变量时,称之为结构指针变量。结构指针变量中的值是所指向 的结构变量的首地址。通过结构指针即可访问该结构变量,这与数组指针和函数指针的情况是相 同的。
结构指针变量说明的一般形式为:
struct 结构名 *结构指针变量名
例如,在前面的例题中定义了stu这个结构,如要说明一个指向stu的指针变量pstu, 可写为:
struct stu *pstu; //定义了指针只能指向stu结构体类型的结构体变量
当然也可在定义stu结构时同时说明pstu。与前面讨论的各类指针变量相同,结构指针变量也必须 要先赋值后才能使用。
赋值是把结构变量的首地址赋予该指针变量,不能把结构名赋予该指针变量。
如果boy是被说明为stu类型的结构变量, 则:
pstu=&boy 是正确的,而: pstu=&stu 是错误的。
2、结构名、结构体变量名、结构体指针
结构名和结构变量是两个不同的概念,不能混淆。结构名只能表示一个结构形式,编译系统并不 对它分配内存空间。只有当某变量被说明为这种类型的结构时,才对该变量分配存储空间。结构 指针变量,就是用来存储结构体变量地址的,就能更方便地访问结构变量的各个成员。
十、结构体指针间接访问成员值
1、结构体指针间接访问成员值
其访问的一般形式为:
(*结构指针变量).成员名
或为:
结构指针变量->成员名
例如: (*pstu).num 或者: pstu->num
应该注意(*pstu)两侧的括号不可少,因为成员符“.”的优先级高于“*”。 如去掉括号写作*pstu.num则等效于*(pstu.num),这样,意义就完全不对了。
十一、结构体变量及成员作为函数参数
在ANSI C标准中允许用结构变量作函数参数进行整体传送。但是这种传送要将全部成员逐个传
送,特别是成员为数组时将会使传送的时间和空间开销很大,严重地降低了程序的效率。因此最好的办法就是使用指针,即用指针变量作函数参数进行传送。这时由实参传向形参的只是地址,从而减少了时间和空间的开销
-------Java培训、Android培训、iOS培训、.Net培训、期待与您交流! -------
五、结构体变量存储原理
1、结构体存储原理
结构名只能表示一个结构形式,编译系统并不对它分配内存空间。只有当某变量被说明为这
种类型的结构时,才对该变量分配存储空间。
内存是以字节为单位编号,但一些硬件平台对某些特定类型的数据只能从某些特定地址开始, 比如从偶地址开始。若不按照适合其平台的要求对数据存放进行对齐,会影响到效率。 因此,在内存中,各类型的数据是按照一定的规则在内存中存放的,这就是对齐问题。
结构体占用的内存空间是每个成员占用的字节数之和(考虑对齐问题)。
2、结构体数据成员对齐的意义
许多实际的计算机系统对基本类型数据在内存中存放的位置有限制,它们会要求这些数据的起始 地址的值是某个数k的倍数,这就是所谓的内存对齐,而这个k则被称为该数据类型的对齐模数 (alignment modulus)。
这种强制的要求一来简化了处理器与内存之间传输系统的设计,二来可以提升读取数据的速度。 比如这么一种处理器,它每次读写内存的时候都从某个8倍数的地址开始,一次读出或写入8个字 节的数据,假如软件能保证double类型的数据都从8倍数地址开始,那么读或写一个double类型数 据就只需要一次内存操作。否则,我们就可能需要两次内存操作才能完成这个动作,因为数据或 许恰好横跨在两个符合对齐要求的8字节内存块上。
3、结构体对齐的含义
1)结构体总长度
2)结构体内各数据成员的内存对齐,即该数据成员相对结构体的起始位置
六、结构体作用域
1、作用域概述
结构类型定义在函数内部的作用域与局部变量的作用域是相同的
函数外部定义的结构体类型类似全局变量
全局作用域:从定义的那一行开始直到本文件结束为止
2、作用域分类
结构体根据作用于可以分为全局结构体、局部结构体
<span style="font-size:14px;">#include <stdio.h> //定义一个全局的结构体 struct Person{ int age; char *name; }; int main(int argc, const char * argv[]) { //定义结构体变量 struct Person p1={18,"胡一刀"}; //此处是可以的 char *str ="aa"; str="bbb"; p1.name = "苗人凤"; printf("age = %d\nname = %s\n",p1.age,p1.name); { //定义一个结构体 //定义局部的结构体,这个结构体和全局的结构体同名 struct Person{ int age; }; } //此处定义的p2 是局部结构体Person的类型 struct Person p2; p2.name = "户外i"; return 0; }</span>
七、结构体数组概念及定义
1、结构数组概念
数组的元素也可以是结构类型的。因此可以构成结构型数组。结构数组的每一个元素都是具 有相同结构类型的下标结构变量。在实际应用中,经常用结构数组来表示具有相同数据结构的一 个群体。如一个班的学生档案,一个车间职工的工资表等。
2、结构数组定义
定义格式:
struct 结构名
{
成员表列
}数组名[数组长度];
结构体数组定义:
结构体数组定义的第一种方式:
1)定义结构体的同时,定义数组
struct Student
{
int age;
char *name;
int s_no;
float score;
}stu[5];
2)先定义结构体,后定义数组
struct Student boy[5];
例如:定义一个长度为5的数组,其中每一个元素都是 stu结构类型
struct stu
{
int num;
char *name;
char sex;
float score;
}boy[5];
定义了一个结构数组boy,共有5个元素,boy[0]~boy[4]。每个数组元素都具有struct stu的结 构形式。
<span d342 style="font-size:14px;">#include <stdio.h> int main(int argc, const char * argv[]) { struct Student{ int age; char *name; int s_no; float score; }stu[5]; struct Student boy[5]; return 0; }</span>
八、结构体数组初始化
1、结构数组的初始化
//1、定义结构体数组的时候,进行初始化
struct Student{
char name[20];
int age;
}boys[3]={{"sb",18},{"zbz",38},{"cgx",28}};
//2、定义的同时进行初始化
struct Student girls[2]={{"fengjie",18},{"cjk",28}};
//3、先定义后初始化,整体赋值
struct Student ds[2];
ds[0]=(struct Student){"xzmly",18};
ds[1]=(struct Student){"bdjy",18};
//4、先定义结构体数组,后初始化
struct Student stu[2];
//stu[0].name = "zhangsan";
//strcpy(stu[0].name,"zhangsan");
scanf("%s",stu[0].name);
2、结构数组遍历
struct Student{
char name[20];
int age;
}boys[3]={{"sb",18},{"zbz",38},{"cgx",28}};
for(int i=0;i<3;i++){
printf("name:%s,age:%d\n",boys[i].name,boys[i].age);
}
<span style="font-size:14px;">#include <stdio.h> void test1(){ //结构体数组的初始化方法 //1、定义结构体数组的时候,进行初始化 struct Student{ char name[20]; int age; }boys[3]={{"sb",18},{"zbz",38},{"cgx",28}}; //2、定义的同时进行初始化 struct Student girls[2]={{"fengjie",18},{"cjk",28}}; //3、先定义后初始化,整体赋值 struct Student ds[2]; ds[0]=(struct Student){"xzmly",18}; ds[1]=(struct Student){"bdjy",18}; //4、先定义结构体数组,后初始化 struct Student stu[2]; //stu[0].name = "zhangsan"; //strcpy(stu[0].name,"zhangsan"); scanf("%s",stu[0].name); stu[0].age = 19; //2、结构数组的遍历********** for(int i=0;i<3;i++){ printf("name:%s,age:%d\n",boys[i].name,boys[i].age); } } int main(int argc, const char * argv[]) { //结构体 struct stu{ int num; char *name; char sex; float score; }; //1、定义结构体数组 struct stu boy[5]={ {101,"Li ping",'F',45}, {102,"Zhang ping",'M',62.5}, {103,"He fang",'F',92.5}, {104,"Cheng ling",'M',87}, {105,"Wang ming",'M',58}}; //2、有一个循环 // float sum = 0.0f; int count=0; //保存不及格的人数 for (int i=0; i<5; i++) { // 计算总成绩 sum+=boy[i].score; // 判断成绩是否小于60 ,如果小于了60 要让计算器+1 if (boy[i].score<60) { count++; }else if (boy[i].score>=80 && boy[i].score<=100){ // 判断是否大于80小于100 // 如果在这个区间,应该输出姓名和成绩 printf("姓名:%s,成绩:%.2f\n",boy[i].name,boy[i].score); } } printf("平均值:%.2f\n",sum/5); printf("不及格人得个数:%d\n",count); return 0; }</span>
九、结构指针定义和初始化
1、指向结构体变量的指针
一个指针变量当用来指向一个结构变量时,称之为结构指针变量。结构指针变量中的值是所指向 的结构变量的首地址。通过结构指针即可访问该结构变量,这与数组指针和函数指针的情况是相 同的。
结构指针变量说明的一般形式为:
struct 结构名 *结构指针变量名
例如,在前面的例题中定义了stu这个结构,如要说明一个指向stu的指针变量pstu, 可写为:
struct stu *pstu; //定义了指针只能指向stu结构体类型的结构体变量
当然也可在定义stu结构时同时说明pstu。与前面讨论的各类指针变量相同,结构指针变量也必须 要先赋值后才能使用。
赋值是把结构变量的首地址赋予该指针变量,不能把结构名赋予该指针变量。
如果boy是被说明为stu类型的结构变量, 则:
pstu=&boy 是正确的,而: pstu=&stu 是错误的。
2、结构名、结构体变量名、结构体指针
结构名和结构变量是两个不同的概念,不能混淆。结构名只能表示一个结构形式,编译系统并不 对它分配内存空间。只有当某变量被说明为这种类型的结构时,才对该变量分配存储空间。结构 指针变量,就是用来存储结构体变量地址的,就能更方便地访问结构变量的各个成员。
<span style="font-size:14px;">#include <stdio.h> int main(int argc, const char * argv[]) { //定义一个结构体 struct Car{ int lunzi; int speed; }car1; //定义一个结构体指针 struct Car *p=NULL; //定义一个结构体指针变量 p = &car1;//正确的 //p = &Car;//错误的 //结构体名:Car //结构体变量名 car1 //结构体指针: p return 0; }</span>
十、结构体指针间接访问成员值
1、结构体指针间接访问成员值
其访问的一般形式为:
(*结构指针变量).成员名
或为:
结构指针变量->成员名
例如: (*pstu).num 或者: pstu->num
应该注意(*pstu)两侧的括号不可少,因为成员符“.”的优先级高于“*”。 如去掉括号写作*pstu.num则等效于*(pstu.num),这样,意义就完全不对了。
<span style="font-size:14px;">#include <stdio.h> int main(int argc, const char * argv[]) { struct Student{ int age; char *name; }; //定义一个结构体的变量 struct Student stu1={18,"张三丰"}; //结构体变量的成员值有2个 // stu1.age 值 18 // stu1.name 值 张三丰 // 2、用结构体指针间接的访问结构体变量的成员值 // struct Student *p = &stu1; printf("姓名:%s,年龄:%d\n",(*p).name,(*p).age); printf("姓名:%s,年龄:%d\n",p->name,p->age); return 0; }</span>
十一、结构体变量及成员作为函数参数
在ANSI C标准中允许用结构变量作函数参数进行整体传送。但是这种传送要将全部成员逐个传
送,特别是成员为数组时将会使传送的时间和空间开销很大,严重地降低了程序的效率。因此最好的办法就是使用指针,即用指针变量作函数参数进行传送。这时由实参传向形参的只是地址,从而减少了时间和空间的开销
<span style="font-size:14px;">#include <stdio.h> struct Car{ int lunzi; int speed; }; void xiuche(int n){ n = 2; } //用结构体变量作为函数的参数 void xiuche1(struct Car c1){ c1.lunzi = 2; } int main(int argc, const char * argv[]) { //定义一个结构体变量 struct Car car1={4,200}; //car1.lunzi 结构体变量成员值 4 //1、用结构体变量的成员值作为函数的参数,实质是值传递 xiuche(car1.lunzi); //2、用结构体变量作为函数的参数 //实质上还是值传递 xiuche1(car1); printf("%d\n",car1.lunzi); //4 return 0; }</span>
-------Java培训、Android培训、iOS培训、.Net培训、期待与您交流! -------
相关文章推荐
- Lua和C语言的交互详解
- C#中结构体和字节数组转换实现
- 关于C语言中参数的传值问题
- 简要对比C语言中三个用于退出进程的函数
- 深入C++中API的问题详解
- 基于C语言string函数的详解
- C语言中fchdir()函数和rewinddir()函数的使用详解
- C语言内存对齐实例详解
- 使用C语言判断英文字符大小写的方法
- c语言实现的带通配符匹配算法
- C语言实现顺序表基本操作汇总
- C语言中计算正弦的相关函数总结
- 使用C语言详解霍夫曼树数据结构
- 探讨C语言的那些小秘密之断言
- C语言实现BMP转换JPG的方法
- 深入探讨C语言中局部变量与全局变量在内存中的存放位置
- C语言查找数组里数字重复次数的方法
- C语言泛型编程实例教程
- C语言中使用lex统计文本文件字符数
- 在C语言中转换时间的基本方法介绍