黑马程序员——C语言基础---结构体2

                                                                            ------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 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培训、期待与您交流! -------

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值