目录
结构体
结构体
为什么会出现结构体呢?
像C语言本身具有的类型如:char、short、int、long、float、double这些类型虽然都有,而如描述清楚一个人的话,人是一个复杂的对象,有名字+年龄+性别+……和其他属性;描述一本书的话,书也是一个复杂的对象,如:书名+作者+出版社+定价+书号+……其他属性,……
对于描述人,名字是字符串,年龄是数字,性别最多是字符串,所以可以把这些属性(基础的属性)组合起来,此时就有了结构体的概念。
结构体就是把这种不同的属性集合在一起,包含在一起,这时就有了结构体。
结构体是C语言特别重要的知识点,结构体使得C语言有能力描述复杂类型。
比如描述学生,学生包含:名字+年龄+学号这几项信息。
比如现在用C语言描述一个学生:(这时就用到结构体)
//定义一个结构体:
//struct是结构体关键字
//定义一个结构体的时候,后面需要起一个名字,比如:Stu(表明是定义的是学生这样一个结构体类型)
//即:struct Stu
//struct Stu
//{
//这个大括号就是把描述学生的相关属性括在一起,因为不可能一个变量就描述清楚
//};
struct Stu
{
char name[20];//描述名字,字符串放到字符里去,表示可以放20个字符
int age;//描述年龄,年龄是一个数字,用int
char sex[10];//性别,性别是汉字,给10个字符的空间
};
//即这是定义(学生)结构体的方式,
//Stu是结构体的标签名,大括号里放的是结构体的部分成员,来描述这个结构体对象的
#include
struct Stu
{
char name[];//这个方括号里的数字不能省略,要对name初始化的,要创建空间的,即这个空间大小必须明确指定
int age;
char sex[10];
};
//这时候如何去使用它呢?
int main()
{
struct Stu zhangsan;
struct Stu lisi;//这个Stu是类型,在类型定义时,name还没有空间,也没有对它初始化,所以[20]必须写上
//这个地方的20是用来说明name这个空间必须20个字符,不能根据初始化的内容来确定它的大小。
//当我们用struct Stu来创建zhangsan的时候,zhnagsan这个对象的相关属性里面name就有20个字符,age是4个字节,sex是10个字符的空间
//这时就可以对它进行初始化了,
return 0;
}
#include
struct Stu
{
char name[20];
int age;
char sex[10];
};
//这一部分是定义一个结构体类型
int main()
{
//有了上述定义的结构体类型之后,用它来创建变量:zhangsan、lizi;有了这个变量后可以对它进行初始化
struct Stu zhangsan = {"张三",30,"男"};
//zhangsan的信息包含几项,需要用大括号括起来,这样给它初始化:叫张三,30岁,性别男。
struct Stu lisi = {"李四",24,"保密"};
//对lizi进行初始化:叫李四,年龄24岁,性别保密。
//把这些信息放进去之后,能打印吗?
printf("%s %d %sn");//名字是字符串,用%s来打印;年龄是整数,用%d;性别是字符串,用%s。
//这确定了打印格式
printf("%s %d %sn", zhangsan.name, zhangsan.age, zhangsan.sex);
//要打印的对象是:zhangsan,zhangsan里面有数据:name、age、sex,(这三个东西叫结构体的结构成员)怎么能访问到它的成员呢?——敲.(点)后面成员就显现出来了。.name就是张三自己的name成员,其他也如此)
printf("%s %d %sn", lisi.name, lisi.age, lisi.sex);
return 0;
}
//注:双引号是用来引一个字符串的,字符用单引号,其他不用引,年龄不引双引号,年龄(数字)是一个整型
//name是20,sex是10,大小是根据需要设置的,根据需求来自己设置其大小name可能长
这里用到了一个操作符——叫点操作符:.
是结构体成员访问的操作符。
那它是如何使用的呢?
.(点)操作符使用的语法规则是:
结构体变量.结构体成员
用到结构体类型的场景:描述一些复杂的对象。写一个商场:描述货品;描述学生管理系统等等。
struct里初始化时的值是自己想要的结果。
数组名不需要取地址,因为数组就是一个地址。数组的大小是指定的元素个数乘以一个元素有多大是总大小。
结构体有全局变量和局部变量。上述创建的张三和李四是在main()函数的大括号里创建的,是局部变量。
一个地址是二进制序列,占4个字节,这个地址放到一个变量里,那这个变量所占空间的大小是4字节。
'a:——是字符,1个字节
“中国”——这是两个汉字,放到一个字符串里,后面有‘ ’,而一个汉字是占两个字节空间的。
#include
int main()
{
printf("%dn", strlen("中国"));//测试“中国”这个字符串的长度
return 0;
}//运行结果:4
//即一个汉字是占2个字节空间的。
结构体成员访问的操作符:.(点)、->(箭头)
->(箭头)这个操作符的用法:
#define _CRT_SECURE_NO_WARNINGS 1
//#include
//struct Stu
//{
// char name[20];
// int age;
// char sex[10];
//};
//int main()
//{
// struct Stu zhangsan = { "张三",30,"男" };
// struct Stu lisi = { "李四",24,"保密" };//lisi是一个变量,用struct Stu这个类型创建的lisi
// printf("%s %d %sn", zhangsan.name, zhangsan.age, zhangsan.sex);
// printf("%s %d %sn", lisi.name, lisi.age, lisi.sex);
//
// return 0;
//}
//若取lisi这个变量的地址呢?用取地址符即可把它的地址取出来了
//lisi这个变量的类型是struct Stu,&lisi的名字叫pl,它的类型是struct Stu *
//这个*告诉我们pl这个是指针,前面的struct Stu告诉我们pl指向的lisi的类型是struct Stu
//#include
//struct Stu
//{
// char name[20];
// int age;
// char sex[10];
//};
//int main()
//{
// struct Stu zhangsan = { "张三",30,"男" };
// struct Stu lisi = { "李四",24,"保密" };
// struct Stu* pl = &lisi;
// printf("%s %d %s",(*pl).name,(*pl).age,(*pl).sex );
因为pl是一个指针,它指向了lisi这个变量,printf中的*pl是对pl进行解引用操作,找到的是lisi这个对象,
当有了lisi这个对象后,也要找到它的成员,再.(点)一下即可
// //printf("%s %d %sn", zhangsan.name, zhangsan.age, zhangsan.sex);
// //printf("%s %d %sn", lisi.name, lisi.age, lisi.sex);
// return 0;
//}
//运行结果是:李四 24 保密
//先解引用,再访问成员内部
//简洁的语法形式是:
//pl是一种指针,有一种指向关系,指向的是李四,所以:
//printf("%s %d %sn",pl->name)
//pl->name完全等价于*pl.name
//pl->name的意思是找到pl指向的对象李四的成员内的name
#include
struct Stu
{
char name[20];
int age;
char sex[10];
};
int main()
{
struct Stu zhangsan = { "张三",30,"男" };
struct Stu lisi = { "李四",24,"保密" };
struct Stu* pl = &lisi;
struct Stu* pd = &zhangsan;
printf("%s %d %sn", zhangsan.name, zhangsan.age, zhangsan.sex);
printf("%s %d %sn", lisi.name, lisi.age, lisi.sex);
//printf("%s %d %sn", *pl->name, *pl->age, *pl->sex);错误
printf("%s %d %sn", pd->name, pd->age, pd->sex);
printf("%s %d %sn", pl->name, pl->age, pl->sex);
return 0;
}//运行结果是:张三 30 男
//李四 24 保密
//张三 30 男
//李四 24 保密
//其中:->是结构成员访问的操作符,其用法是:
//左边是一个结构体指针,右边是结构体成员
总结:
.(点)
结构体成员访问的操作符
结构体变量.结构体变量
应用场景:若拿到的是结构体变量(如zhangsan、lisi)
//printf("%s %d %sn",(*pl).name,(*pl).age,(*pl).sex );
->(箭头)
结构式成员访问的操作符
结构体指针->结构体成员
应用场景:若拿到的是结构体指针的变量
//printf("%s %d %sn", pl->name, pl->age, pl->sex);
试比较:(注意语法形式)
#define _CRT_SECURE_NO_WARNINGS 1
#include
struct Stu
{
char name[20];
int age;
char sex[10];
};
int main()
{
struct Stu zhangsan = { "张三",30,"男" };
struct Stu lisi = { "李四",24,"保密" };
struct Stu* pl = &zhangsan;
printf("%s %d %sn", zhangsan.name, zhangsan.age, zhangsan.sex);
printf("%s %d %sn", (*pl).name, (*pl).age, (*pl).sex);
printf("%s %d %sn", pl->name, pl->age, pl->sex);
return 0;
}//运行结果是: 张三 30 男
// 张三 30 男
// 张三 30 男
pl存的是lisi的地址,并不是lisi,而是指针变量,若要找到lisi,需要解引用一下(加*),解引用一下才是lisi,然后.name找到其结构体成员。pl结构体指针pl->相当于对pl解引用了。
注:pl是地址,而*pl是lisi(它指向的那个变量)
结构体变量可以被修改,既然是变量,它就可以被修改。



