C–七、结构体
为什么使用结构体?
如果我们需要对一个公司的员工信息进行记录,员工信息里包括了年龄,姓名,工资,电话号码等等。有整形,浮点型以及字符串。那我们该怎么记录呢?这便有了结构体的概念。
可以与数组进行类比,数组是数据类型一致的数据集合。但如果要使用数据类型不同的数据结合,就要使用结构体了。
demo:
struct Elector
{
char name[32];
double salary;
int age;
};
注意:
- 结构体可以当作一个模版,一般不赋给其具体的值。在实际使用时,也不是每一项都一定用得到。
- 结构体后面有个分号;
成员列表
上述代码中的name,salary,age的结合叫成员列表,也可以称为域表,每个成员都是结构体中的域。
声明的同时定义变量
struct Elector
{
char name[32];
double salary;
int age;
}ele1,ele2;
这种方式建议尽量少用。
结构体的初始化
#include <stdio.h>
struct Elector
{
char name[32];
double salary;
int age;
};
int main()
{
//1.初始化方式1.需要按照结构体中的成员列表顺序赋值
struct Elector ele1 = {"LiQiaoQiao",5200.0,19};
//1.初始化方式2:通过点运算符
struct Elector ele2;
//ele2.name = "Zhang";错误的方式
strcpy(ele2.name,"Zhang");
ele2.salary = 5200.0;
ele2.age = 20;
printf("%s,%f,%d\n",ele1.name,ele1.salary,ele1.age);
printf("%s,%f,%d\n",ele2.name,ele2.salary,ele2.age);
return 0;
}
reuslt:
注意:
使用点运算符给结构体中的字符数组赋值时,要使用strcpy.
结构体数组
#include <stdio.h>
#include <string.h>
struct student
{
int num;
char name [ 32];
char sex;
int age;
double score;
char addr [32];
};
int main (){
int arr[3] = { 1,2,3};
int i;
int len;
struct student arr2[3]= {{ 2,"张三",'g',17,99.5,"北京"},
{ 3,"李四",'M',18,89.2,"上海"},
{ 4,"王五",'f',19,100,"内蒙"}
};
len = sizeof (arr2)/sizeof (arr2[0]);
for(i = 0;i< len;i++){
printf("学号:%d,年龄:%d,分数:%lf,名字:%s,地址:号s\n",
arr2[i].num,arr2[i].age,arr2[i].score,arr2[i].name,arr2[i].addr);
}
return 0;
}
形式上类似于二位数组
结构体指针
前情提要:
- 指针就是地址。
- 指针变量就是存放地址的变量结构体也是变量。
- 变量访问有两种方式:
- 变量名
- 地址
通过结构体变量地址来访问该结构体需要一个变量来存储地址:
这和之前说的指针,其实是一样的。只是指针类型是结构体
int a;
int *p;
p = &a;
struct Test t;
struct Test *p;
p = &t;
通过结构体指针访问结构体
使用"->"运算符访问
#include <stdio.h>
struct Person
{
char name[32];
int age;
};
int main()
{
struct Person p = {"张三",19};
struct Person *pp = &p;
printf("%s,%d\n",p.name,p.age);
printf("%s,%d\n",pp->name,pp->age);
return 0;
}
区分点运算符和 "->"运算符用的时机
- 使用结构体变量访问成员变量用"."运算符
- 使用结构体指针访问成员列表用"->"运算符
联合体/共同体
同一个内存空间存放类型不同,不同类型的变量共享一块空间
共同体与结构体的区别和联系:
- 结构体元素有各自单独空间
- 共用体元素共享空间,空间大小由最大类型确定
- 结构体元素互不影响共用体赋值会导致覆盖
覆盖案例:
#include <stdio.h>
struct TestS
{
int idata;
char cdata;
int ddata;
};
union TestU
{
int idata;
char cdata;
int ddata;
};
int main()
{
struct TestS testS;
union TestU testU;
testS.idata = 10;
testS.cdata = 'a';
testS.ddata = 20;
printf("sizeof TestS :%d\n",sizeof(testS));
printf("sizeof TestU :%d\n",sizeof(testU));
printf("struct idata:%p,%d\n",&testS.idata,testS.idata);
printf("struct cdata:%p,%c\n",&testS.cdata,testS.cdata);
printf("struct ddata:%p,%d\n",&testS.ddata,testS.ddata);
testU.idata = 10;
testU.ddata = 20;
testU.cdata = 'a';
printf("union cdata:%d\n",testU.cdata);
printf("union idata:%p\n",&testU.idata,testU.idata);
printf("union cdata:%p\n",&testU.cdata,testU.cdata);
printf("union ddata:%p\n",&testU.ddata,testU.ddata);
return 0;
}
result:
typedef关键字
作用:给已经有的变量类型起名字。一般配合结构体用,更加方便,不用每次都要struct开头
demo:
#include <stdio.h>
typedef struct
{
int num;
char name[32];
}Person,*pPerson;
void printInfo(Person p){
printf("%d,%s\n",p.num,p.name);
}
void printInfo2(pPerson p){
printf("%d,%s\n",(*p).num,(*p).name);
}
void printInfo3(Person* p){
printf("%d,%s\n",(*p).num,(*p).name);
}
int main()
{
Person p1 = {1,"a"};
Person p2 = {2,"b"};
printInfo(p1);
printInfo(p2);
pPerson p3 = &p1;
pPerson p4 = &p2;
printInfo2(p3);
printInfo2(p4);
Person *p5 = &p1;
Person *p6 = &p2;
printInfo3(p5);
printInfo3(p6);
return 0;
}
result:
枚举类型
可以直接忽略枚举类型名,直接定义枚举变量
demo:
#include <stdio.h>
enum {sun,mon,tus = 3,wed,thr,fri,sat}w1,w2;
int main()
{
w1 = sun;
w2 = tus;
printf("%d\n",w1);
printf("%d\n",w2);
printf("%d\n",sat);
return 0;
}
result: