C语言中的自定义类型:struct结构体
1.C语言中的结构体概述
C
语言中的2种类型:原生类型(如int
、char
等)和自定义类型(struct
,enum
等)。结构体类型是是C
语言中的用户自定义类型,主要功能是对功能相关的数据进行封装,它是一个或多个变量的集合,这些变量的类型可以不同。
例如一名学生可以由姓名和性别来描述,结构体中的成员也可以是一个结构体,例如名字由姓+名来描述。结构体由关键字struct
来声明。
2.C语言中结构体的定义和使用
结构体使用时可以先定义好结构体类型,然后再用定义好的类型来定义变量。
结构体的几种定义方式:
- 1.
struct 结构体名{...};
直接定义一个结构体。
#include<stdio.h>
struct student //定义结构体类型
{
char name[20];
int age;
};
int main(int argc,char**argv)
{
struct student a;//用定义好的结构体类型来定义变量
a.age=20;//访问结构体成员
printf("%d.\n",a.age);
return 0;
}
- 2.结构体也可以在定义结构体类型的同时定义结构体变量,下面这段代码就是在定义了一个
struct student
结构体类型的同时定义了一个struct student
类型的变量stu
:
#include<stdio.h>
struct student
{
char name[20];
int age;
}stu;//定义结构体类型的同时定义了一个struct student类型的变量stu
int main(int argc,char**argv)
{
stu.age=20;//访问结构体成员
printf("%d.\n",stu.age);
return 0;
}
- 3.也可以使用
typedef
来对结构体类型重命名,例如下面这段代码,但是此时{}
后面跟着的stu
是新的类型名,而不再是个变量:
#include<stdio.h>
typedef struct student
{
char name[20];
int age;
}stu;//stu是新的类型名 而不是一个变量
int main(int argc,char**argv)
{
stu a;
a.age=20;
printf("%d.\n",a.age);
return 0;
}
3.从数组到结构体的进步之处
结构体可以认为是从数组发展而来的。其实数组和结构体都算是数据结构的范畴了,数组就是最简单的数据结构、结构体比数组更复杂一些,链表、哈希表之类的比结构体又复杂一些;二叉树、图等又更复杂一些。
但是数组有2个明显的缺陷:
- 1.定义时必须明确给出大小,且这个大小在以后不能再更改。
- 2.数组要求所有的元素的类型必须一致,更复杂的数据结构就致力于解决数组的这两个缺陷。
结构体就是用来解决数组的第二个缺陷的,可以将结构体理解为一个其中元素类型可以不相同的数组。结构体完全可以取代数组,只是在数组可用的范围内数组比结构体更简单。
4.结构体变量中的元素访问
数组中元素的访问方式表面上有2种:数组下标方式和指针方式,实质上这两种都是指针方式访问。
结构体变量中的元素访问方式也是一种,用 .
或者 ->
的方式来访问。当通过变量名来访问成员是就用变量名.成员名
来访问;当通过指针来访问成员时,就用指针名->成员名
来访问,举个栗子:
#include<stdio.h>
#include<stdlib.h>
typedef struct student
{ //定义结构体类型
char name[20];
int age;
}stu;//stu是新的类型名 而不是一个变量
int main(int argc,char**argv)
{
//通过变量名来访问成员是就用变量名.成员名来访问
stu a;
a.age=20;
printf("%d.\n",a.age);
//通过指针来访问成员时,就用指针名->成员名来访问
stu* pa=(stu*)malloc(sizeof(stu));
//C++可以用new
//stu* pa=new stu;
pa->age=30;
printf("%d.\n",pa->age);
return 0;
}
这里要注意的就是第17行,当定义一个结构体指针的时候还要手动申请一个该结构体的内存,然后把返回的指针给声明的结构体指针,才能用
->
正确引用。否则内存中只分配了指针的内存,没有分配结构体的内存,结构体实际上是不存在的。这时候用->
引用会导致Segmentation fault (core dumped)
。
结构体的访问方式有点类似于数组下标的方式,结构体变量成员的 .
或者 ->
访问本质上也是用指针来访问的。
通过指针来访问结构体成员,指针加的值需要考虑到结构体内存对齐:
#include<stdio.h>
struct myStruct
{
int a;
double b;
char c;
};
int main(int argc,char**argv)
{
struct myStruct s1;
s1.a = 12;
s1.b = 5.5;
s1.c = 'a';
int*p1 = (int*)(&s1);
printf("s1.a = %d.\n",*p1);
double* p2 = (double*)(p1+2);
printf("s1.b = %lf.\n",*p2);
char*p3 = (char*)(p1+4);
printf("s1.c = %c.\n",*p3);
return 0;
}
输出:
s1.a = 12.
s1.b = 5.500000.
s1.c = a.