在C语言的世界里构造类型有:数组、结构体、联合体、枚举四种数据类型,考虑到结构体还是比较常用,遂在此特开一篇文章单独说它。
一、结构体
C语言属于面向过程语言,没有后来出现的C++ 、Java这些语言,有面向对象的特征,所以也就没有类的概念。在C语言里面,如果需要去描述一类事物,只能使用结构体去描述。它可以把众多不同的类型属性包裹在一起,形成一个独立的个体看待。看结构体的时候可以把它看成是我们自己定义的类型。
1.1 结构体语法
- 声明结构体
//语法结构
struct 结构体名称{
成员类型1,成名名称1;
成员类型2, 成员名称2
};
//具体示例
struct student{
char name[20];
int age;
};
1.2 基本操作
- 初始化结构体
结构体声明之后仅仅相当于是对编译器表态,有一个我们自己定义的类型。如果需要使用结果体,则需要去定义出来结构体变量,然后完成初始化赋值或者通过结构体变量.成员的方式完成后续赋值。需要注意的是, 由于结构体可以认为是我们自己定义的一种类型,所以即便是创建变量,也需要在student前面加上 struct 关键字,否则即会出现错误。
#include <stdio.h>
//声明结构体
struct student{
char name[20];
int age;
};
int main(){
//创建结构体变量, 等价于 int a ;
struct student stu;
//创建结构体变量,同时初始化
struct student stu = {"张三" , 28};
}
- 操作成员
创建好结构体变量后,后续可以通过 变量 . 成员 方式操作成员(可以取值和赋值), 看起来这种语法后续的c++ 和 Java的对象.成员方式一样。
#include <stdio.h>
#include <string.h>
//声明结构体
struct student{
char name[20];
int age;
};
int main(){
//1. 创建结构体变量, 等价于 int a ;
struct student stu1;
//2. 赋值
// 字符串name是数组形式声明,所以只能使用拷贝方式赋值
strcpy(stu1.name , "李四");
stu1.age = 18;
//3. 然后再取值打印
printf("name=%s\n" , stu1.name);
printf("age=%d\n" , stu1.age);
//4. 创建结构体变量,同时初始化
struct student stu2= {"张三" , 28};
//5. 打印
printf("name2=%s\n" , stu2.name);
printf("age2=%d\n" , stu2.age);
return 0 ;
}
1.3 结构体与数组
结构体和数组也是可以联系起来的,描述一个学生,我们需要创建一个结构体变量,那么当我们需要描述很多学生(这一种类事物)的时候,就可以使用数组来存储了。
#include <stdio.h>
#include <string.h>
//声明结构体
struct student{
char name[20];
int age;
};
int main(){
//创建结构体数组
struct student stus[4] ={
{"张三" , 18},
{"李四" , 19},
{"王五" , 20},
{"赵六" , 21}
};
//遍历数组
int len = sizeof(stus) / sizeof (struct student );
for(int i = 0 ; i < len ; i++){
//取出每一个元素:: 每一个元素是一个结构体变量
struct student s = stus[i];
printf("姓名: %s \n" , s.name);
printf("年龄: %d \n" , s.age);
printf("\n");
}
return 0 ;
}
柯南有话说:
1. 在给结构体数组初始化赋值的时候,需要明白它比较特殊,不像以前的基本数据类型数据那么简单,直接放一个简单的数字、字符就可以。它需要的是一个结构体变量。
2. 其实不要因为是结构体数组就觉得恐惧, 仍然把它当成是数组来看待即可,唯一的不同只是它的元素有所差异,为了描述数组的元素是一个结构体,在里面我们直接使用 { } 来完成赋值。
3. 遍历数组取出每一个元素的时候,要明白拿到的是一个结构体变量,此时就按照以前操作结构体变量的做法一样,使用 . 的方式获取每一个成员的数据即可。
1.4 结构与指针
结构体可以认为是我们自己定义的一种类型,与其他默认的基本类型一样,也是可以定义出结构体类型(我们自己定义的类型)的指针的。
#include <stdio.h>
#include <string.h>
//声明结构体
struct student{
char name[20];
int age;
};
int main(){
//定义结构体变量 s1
struct student s1 = {"张三" , 18};
//定义指针 p1 指向 s1
struct student * p1 = &s1;
//使用指针操作结构体成员
//1. 先解引用得到变量,然后再使用 . 的方式操作
printf("name=%s \n" , (*p1).name);
printf("age=%d \n" , (*p1).age);
printf("\n");
//2. 直接使用指针 配合 -> 符号操作成员
printf("name=%s \n" , p1->name);
printf("age=%d \n" , p1->age);
return 0 ;
}
柯南有话说
1. 不管是结构体还是结构体指针,在定义的时候都需要加上 struct 关键字,因为这是我们自己定义的类型,编译器不识别它。
2. 有了结构体指针之后,可以有两种方式操作真正的结构体的成员 ,一是先解引用,然后使用 . 的方式操作成员,二是直接在指针的状态下,配合 -> 符号操作成员 。事实上第二种方式更受程序员的喜欢。
二、总结
1. 学习结构体没有其他的窍门,先按照规则把入门代码写出来,然后再去思考与普通基本类型的区别,这样在获得知识的同时,对于原有知识也变得巩固了。
2. 相比于结构体,联合体使用频率要稍微低一些,除去它的特征有些 "诡异" 之外,其他并没有什么难学,小伙伴若有需要,可以自行百度学习,或者给我发私信,情况允许我会单独再发关于联合体的使用篇章。
3. 枚举这个东西说难不难,说不难也确实难,但是在其他的语言中,枚举都有出场的概率。后续再单独开篇说枚举吧。