电子说
引言
不管什么样的编程语言,数据类型的不断衍生都是为了不同场合对其进行不同处理或管理。 比如单一的变量,我们可以定义成char, short,,int,float, double等;而如果需要管理多个同一类型的数据就可以使用数组来统一管理;那么如果是不同的数据类型,但是彼此是相关联的呢? 此时就可以使用结构体来统一管理,这也是面对对象的基本思想。比如一个学生,他有如下信息: 名字(char *), 年龄(uint8), 成绩(float)等。今天我们就来说说结构体的基本使用,后续再深入研究。
结构体的定义
使用struct关键字定义原生结构体类型
struct people{ char name[20]; int age;};
使用typedef类型自定义结构体类型
typedef struct people1{ char name[20]; int age; }people1_t;
两种方式的有何不同呢? 第一种属于原生结构体类型,在定义变量之前,都需要加上struct people
struct people p1;
而第二种使用typedef关键字自定义了people_t类型(people1_t等同于struct people1), 即在定义变量时,只需要在变量之前写上people_t即刻。
people1_t p2;
这两种方式都可,用户根据自己的习惯选择其中一种即刻,个人推荐第二种,定义比较方便~
定义结构体变量和初始化
如上所述,使用第一种struct people定义结构体变量时,有如下方式:
struct people{ char name[20]; int age;};int main(void){ struct people p1; //使用struct people定义变量p1 return 0;}
或:
//定义类型的同时定义变量struct student{ char name[20]; int age;}std;int main(void){ std.age =23; //直接使用std结构体变量 return 0;}
使用typedef方式定义结构体变量
typedef struct people1{ char name[20]; int age; }people1_t;int main(void){ people1_t p2; return 0;}
接下来我们再介绍结构体的两种方式初始化:
#include 《stdio.h》#include 《string.h》struct people{ char name[20]; int age;};typedef struct people1{ char name[20]; int age; }people1_t;int main(void){ //方式一:在定义的变量的同时初始化 struct people p1 ={ .name = “xiaoming”, .age = 23 }; people1_t p2; //方式二: 定义变量后,再对其初始化 strcpy(&p2.name[0], “xiaohong”); p2.age = 45; printf(“p1.name = %s, age = %d. ”, p1.name, p1.age); printf(“p2.name = %s, age = %d. ”, p2.name, p2.age); return 0;}
编译运行:
结构体的元素访问
在C语言中有两种方式访问,分别是“。”和“-》”, 具体参考如下代码:
#include 《stdio.h》#include 《string.h》#include 《stdlib.h》struct people{ char name[20]; int age;};typedef struct people1{ char name[20]; int age; }people1_t;int main(void){ //定义结构体变量,并初始化 struct people p1 ={ .name = “xiaoming”, .age = 18 }; //定义结构体指针变量 people1_t *p2 = NULL; //申请people1_t结构体大小的堆内存空间,并将得到的起始地址赋予p2 p2 = (people1_t *)malloc(sizeof(people1_t)); if(NULL != p2) { //初始化 strcpy(&p2-》name[0], “xiaohong”); p2-》age = 26; } //结构体变量通过‘。’来访问其元素 printf(“p1.name = %s, age = %d. ”, p1.name, p1.age); //结构体变量通过‘-》’来访问其元素 printf(“p2.name = %s, age = %d. ”, p2-》name, p2-》age);}
编译运行结果:
以上两种方式都是使用下标式访问结构体元素, 那么如何使用指针方式访问呢?
#include 《stdio.h》#include 《string.h》#include 《stdlib.h》struct my_test{ int a; //4 double b; //8 char c; //1};int main(void){ struct my_test s1; s1.a = 12; s1.b = 3.4; s1.c = ‘a’; int *p1 = (int *)&s1; double *p2 = (double *)((long unsigned int)&s1 + 8); char *p3 = (char *)((long unsigned int)&s1 + 8 + 8); printf(“s1.a = %d. ”, s1.a); printf(“s1.b = %.1f. ”, s1.b); printf(“s1.c = %c. ”, s1.c); printf(“===================== ”); printf(“*p1 = %d. ”, *p1); printf(“*p2 = %.1f. ”, *p2); printf(“*p3 = %c. ”, *p3);}
分析:
int *p1 = (int *)&s1,其中&s1为结构体的起始地址,也是首元素a的地址,因此可以通过类型转化后赋值给p1(int *类型,指向int类型的变量a)
double *p2 = (double *)((long unsigned int)&s1 + 8); 其中因为&s1是作为结构体地址,本身是带有数据类型的,我们通过(long unsigned int)将其转化成普通的长整型数值,然后再加上a(8字节)的长度,之后的地址就是结构体第二个元素b的地址了,于是乎将得到的地址转化成double *类型赋值给p2,通过p2来访问。
char *p3 = (char *)((long unsigned int)&s1 + 8 + 8); 与上步骤分析一致, 首先将&s1转化成普通的普通的长整型数值,然后加上元素a 和 元素b的数据类型长度,就得到了元素c的地址,再赋值给p3,通过p3来访问结构体元素c。
编译运行结果:
总结
从数组到结构体的进步之处:数组有2个明显的缺陷:第一个是定义时必须明确给出大小,且这个大小在以后不能再更改(这里不考虑可变数组);第二个是数组要求所有的元素的类型必须一致。
结构体就完美解决了数组的第二个缺陷的,可以将结构体理解为一个其中元素类型可以不相同的数组。结构体完全可以取代数组,只是在数组可用的范围内数组比结构体更简单,使用更方便。
全部0条评论
快来发表一下你的评论吧 !