结构体

是什么结构体

  在编写程序时,我们遇到的不止有简单的变量、数学运算,当我们想要表达一个复杂的数据类型时,但是不巧的是C语言中自带的类型没有时,我们该怎么办呢?
  此时就可以运用到结构体来定义那些复杂的变量类型。结构体这样的语法就提供了“ 自定义类型 ”,所谓结构体就是某些值的集合。我们将一个物体不同的属性,也就是它所包含的不同类型的变量,放到一起,而这个集合我们可以抽象的看成是这个物体。
  我们将一个个对象抽象化,提取其中的核心元素,赋予不同的值,然后表示出来,这样就可以形成同一类型的不同个体。

结构体的定义

  假如,我们想要描述一个学生,我们可以将学生抽象成为一个结构体,把他的基本信息写进这个结构体重,作为他的成员变量:

struct Student
{
    char name[1024];//姓名
    int id;//学号
    char sex;//性别
};

  通过上述代码,我们就定义好的一个名为Student,有三个成员变量name、id、sex,那么如何使用呢?如下所示:

struct Student stu1={“张三”,20201111,’f‘};

  这样我们就定义好了一个结构体变量,并且初始化(下面会详细讲),不过我们看到这样的结构体变量写起来很长,很冗余,每次定义的时候都要加上struct关键字,那么有以下方法可以改进:

struct Student
{
    char name[1024];//姓名
    int id;//学号
    char sex;//性别
};
typedef struct Student student;
student stu1={“张三”,20201111,'f'};

  我们知道typedef关键字的作用是将一个数据类型自定义一个新的名称,所以,在上述代码中倒数第二行,我们使用了typedef这个关键字,所以我们在定义结构体变量的时候,就可以如上述代码最后一行一样,方便简单,省了很多麻烦;不过,我么还可以写成下面的形式:

typedef struct Student
{
    char name[1024];//姓名
    int id;//学号
    char sex;//性别
}student;
student stu1={“张三”,20201111,'f'};

  这样就不用再多写一行了,比较方便,代码看起来结构也比较清晰。

结构体变量的定义及初始化

定义
结构体变量定义的两种方法:
1、在声明时定义:
struct Student
{
    char name[1024];//姓名
    int id;//学号
    char sex;//性别
}stu1, stu2;
  
这种方法,我们定义了两个结构体变量, stu1,stu2,不过在这种情况下,不能使用 typedef,这一点要注意;
2、在使用时定义:
#define _CRT_SECURE_NO_WARNINGS
//添加头文件
#include <stdio.h>
#include <stdlib.h>

typedef struct Student
{
    char name[1024];//姓名
    int id;//学号
    char sex;//性别
}student;
//主函数入口
int main()//主函数,函数入口
{
    student stu1, stu2;
    return 0;
}    
  
上面正是我们在使用时才定义的结构体变量,我们定义了两个结构体变量, stu1,stu2
初始化
结构体变量初始化的两种方法:
1、在声明定义结合在一起时初始化:
struct Student
{
    char name[1024];//姓名
    int id;//学号
    char sex;//性别
}stu1={"张三"20201111,’f‘}, stu2={"小红",20202222,'m'};
  
2、在使用时定义的时候初始化:
#define _CRT_SECURE_NO_WARNINGS
//添加头文件
#include <stdio.h>
#include <stdlib.h>

typedef struct Student
{
    char name[1024];//姓名
    int id;//学号
    char sex;//性别
}student;
//主函数入口
int main()
{
    student stu1={"张三",20201111,'f'};
    student stu2={"小红",20202222,'m'};
    return 0;
}    

注:结构体初始化或者赋值的时候,一定要注意顺序,要和结构体中的属性的顺序一致,否则就会报错。

结构体成员的访问

结构体变量访问成员

  在结构体中,当我么创建一个结构体变量的时候,我么就可以使用这个结构体变量来访问它对应的那些属性;

#define _CRT_SECURE_NO_WARNINGS
//添加头文件
#include <stdio.h>
#include <stdlib.h>
typedef struct Student
{
    char name[1024];//姓名
    int id;//学号
    char sex;//性别
}student;
int main()//主函数,函数入口
{
	Student stu1 = { "张三", 20201111,‘f’ };
	Student stu2 = { "小红", 20202222,‘m’ };
	printf("stu1的姓名为:%s,学号为:%d,性别为:%c\n", stu1.name, stu1.id,stu1.sex);
	printf("stu2的姓名为:%s,学号为:%d,性别为:%c\n", stu2.name, stu2.id,stu2.sex);
	return 0;
}

  通过上面的例子,我么可以看出,我么使用结构体变量访问成员变量时,使用的是.操作符,格式为:结构体变量.成员变量名,这样我么就可以操作到成员变量。

结构体指针访问成员变量

  结构体指针实际上就是将结构体变量的地址赋给指针,然后利用指针来操作成员变量;

#define _CRT_SECURE_NO_WARNINGS
//添加头文件
#include <stdio.h>
#include <stdlib.h>
typedef struct Student
{
    char name[1024];//姓名
    int id;//学号
    char sex;//性别
}student;
//主函数,函数入口
int main()
{
    Student stu1 = { "张三", 20201111,‘f’ };
    Student stu2 =&stu1;
    printf("stu1的姓名为:%s,学号为:%d,性别为:%c\n", stu2->name, stu2->id,stu2->sex);
    return 0;
}

结构体嵌套

  在结构体的使用中,我们可以在一个结构体中,将它的成员变量写成另一个结构体,这就叫做结构体嵌套:

#define _CRT_SECURE_NO_WARNINGS
//添加头文件
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct student
{
    char name[50];//姓名
    int id;//学号
}Student;
typedef struct area
{
    Student students[10];
}Area;
typedef struct city
{
    Area areas[10];
}City;
typedef struct province
{
    City cities[10];
}Province;
typedef struct country
{
    Province provinces[10];
}Country;
//主函数,函数入口
int main()
{
    Country country;
    Country* pCountry = &country;
    country.provinces[0].cities[0].areas[0].students[0].id = 111;
    strcpy(pCountry->provinces[0].cities[0].areas[0].students[0].name, "Misaki");
    printf("学生的学号为:%d,姓名为:%s\n", country.provinces[0].cities[0].areas[0].students[0].id,country.provinces[0].cities[0].areas[0].students[0].name);
    return 0;
}

  这样的结构体嵌套,大家要谨慎使用,因为嵌套时内存的空间分配是成倍增加的,嵌套得越多,占用的内存就会越多,若是太大的话,系统会自我保护,自己关闭程序。

结构体传参

值传递

  这样的传递方式和普通变量一样,形参的改变不会影响实参的变化,所以这样的方式改变结构体变量的成员变量,自身不会有什么改变

#define _CRT_SECURE_NO_WARNINGS
//添加头文件
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct student
{
    char name[50];//姓名
    int id;//学号
        char sex;//性别
}Student;
void Func(Student stu)
{
    stu.id = 20206666;
    printf("在函数内部学生的学号为:%d\n", stu.id);
}
//主函数,函数入口
int main()
{
    Student stu = { "张三", 20201111 ,'f'};
    Func(stu);
    printf("在函数外部学生的学号为:%d\n", stu.id);
    return 0;
}
址传递

  这也和之前的普通变量指针传递一样,外部的改变,是会改变自身的;
  另外还有一个更大的优点,那就是值传递,是会在内存中重新开辟一块空间,而结构体变量所需要的空间往往是很大的,所以,使用址传递的话,就不需要重新创建临时空间,是非常好的,节省空间时间:

#define _CRT_SECURE_NO_WARNINGS
//添加头文件
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct student
{
    char name[50];//姓名
    int id;//学号
        char sex;//性别
}Student;
void Func(Student* stu)//如果需要给一个指向常量的指针则需要改为 const Student* stu;
{
    stu->id = 20206666;
    printf("在函数内部学生的学号为:%d\n", stu->id);
}
//主函数,函数入口
int main()
{
    Student stu = { "张三", 20201111,'f' };
    Func(&stu);
    printf("在函数外部学生的学号为:%d\n", stu.id);
    return 0;
}

博客园发表于 2020-11-08 14:51

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值