您的位置:首页 > 编程语言 > C语言/C++

黑马程序员——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、作用域分类 
结构体根据作用于可以分为全局结构体、局部结构体

<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培训、期待与您交流! -------
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  C语言 结构体