【结构体】
admin
2024-04-11 21:48:09
0

结构体

  • 结构体
    • 1. 结构体的声明
      • 1.1 结构的基础知识
      • 1.2 结构的声明
      • 1.3 结构成员的类型
      • 1.4 结构体变量的定义和初始化
    • 2. 结构体成员的访问

结构体

  • 结构体类型的声明
  • 结构体初始化
  • 结构体成员访问
  • 结构体传参

这里还只是讲一部分关于结构体的内容,更详细的内容在进阶—自定义类型详解中。

1. 结构体的声明

1.1 结构的基础知识

结构是一些值的集合,这些值称为成员变量。结构的每个成员可以是不同类型的变量。

数组是一些相同类型的集合。

结构体是不同类型变量的集合。

我们已经学习了char shor int long float double类型对数据进行描述。

在生活中我们有些复杂对象无法用单一类型进行描述,例如:

人有名字,年龄,电话,住址

书有名字,作者,出版社,定价

在c语言中,为了描述复杂对象,创建了struct关键字。

1.2 结构的声明

struct tag
{member-list;   //成员列表
}variable-list;  //变量列表

tag结构体类型的名字

例如描述一个学生:

struct student
{char name[20];//名字int age;//年龄char sex[5];//性别int hight;//身高
}s1,s2,s3;

这里的s1就是一个学生s2一个学生s3一个学生。

不过这种写法比较少见,因为这里创建的变量s1s2s3是全局变量,一般我们定义为局部变量,不在此定义变量

struct student
{char name[20];//名字int age;//年龄char sex[5];//性别int hight;//身高
};

定义变量

struct student
{char name[20];//名字int age;//年龄char sex[5];//性别int hight;//身高
}s1,s2,s3;//在创建类型同时定义全局变量struct student s5;  //全局变量
int main()
{struct student s4;//局部变量
}

1.3 结构成员的类型

结构的成员可以是标量、数组、指针,甚至是其他结构体。

1.4 结构体变量的定义和初始化

#include 
struct student
{char name[20];//名字int age;//年龄char sex[5];//性别int hight;//身高
};struct pos
{int x;int y;
};
int main()
{struct pos p = { 10,20 };struct student s = { "zhangsan",20,"男",180 };printf("%d %d\n", p.x, p.y);printf("%s %d %s %d\n", s.name, s.age, s.sex, s.hight);
}
//-------------------
//编译器运行结果为
//10 20
//zhangsan 20 男 180

结构体中再嵌套一个结构体

#include 
struct student
{char name[20];//名字int age;//年龄char sex[5];//性别int hight;//身高
};struct pos
{int x;int y;
};struct s
{char c;struct pos p;double d;char str[20];
};
int main()
{struct s ss = { 'x',{100,200},3.14,"hehe" };printf("%c %d %d %lf %s\n", ss.c, ss.p.x, ss.p.y, ss.d, ss.str);
}
//-------------------
//编译器运行结果为
//x 100 200 3.140000 hehe

结构体如何进行指定顺序赋值(不多使用)

#include struct pos
{int x;int y;
};struct s
{char c;struct pos p;double d;char str[20];
};
int main()
{struct s ss = { .d = 3.14,.c = 'x',.p.x=10 };printf("%c %d %d %lf %s\n", ss.c, ss.p.x, ss.p.y, ss.d, ss.str);
}
//------------------
//编译器运行结果为
//x 10 0 3.140000

进行指定赋值,且不完全初始化赋值。

当字符串里面全部都是0的时候,就不打印。

结构体外指定赋值

错误写法

#include 
struct S
{char name[20];int age;
};
int main()
{struct S s = { .age = 20,.name = "zhangsan" };printf("%s %d\n", s.name, s.age);s.age = 30;  //可行s.name = "zhangsanfeng";  //不可行return 0;
}

name是数组名,是首元素的地址,地址是一个门牌号,我们做的应该是把字符串放到地址所指向的空间里,而不是改变地址。

另一种错误写法

*(s.name)="zhangsanfeng";

s.name是数组首元素的地址,name是char类型数组,*(s.name)访问的的是一个字节的首元素空间,放不下一个字符串。

正确写法

#include 
struct S
{char name[20];int age;
};
int main()
{struct S s = { .age = 20,.name = "zhangsan" };printf("%s %d\n", s.name, s.age);s.age = 30;  //可行strcpy(s.name, "zhangsanfeng");printf("%s %d\n", s.name, s.age);return 0;
}
//----------------------
//编译器运行结果为
//zhangsan 20
//zhangsanfeng 30

2. 结构体成员的访问

值传递方式

#include 
struct S
{int date[1000];char buf[100];
};
void print(struct S ss)
{int i = 0;for (i = 0; i < 10; i++){printf("%d ", ss.date[i]);}printf("%s\n", ss.buf);
}
int main()
{struct S s = { {1,2,3},"hehe" };print(s);return 0;
}
//------------------------
//编译器运行结果为
//1 2 3 0 0 0 0 0 0 0 hehe

原理

这里采用的是值传递,直接将变量s的整个内容传递给print函数,将print函数中的ss作为s的一份临时拷贝,进行打印。

同样了解如何打印整型数组和字符数组

#include 
struct S
{int date[1000];char buf[100];
};int main()
{struct S s = { {1,2,3},"hehe" };//结构体成员为整型数组时的打印方式int i = 0;for (i = 0; i < 10; i++){printf("%d ", s.date[i]);}printf("\n");//结构体成员为字符数组时的打印方式printf("%s", s.buf);return 0;
}
//------------------------
//编译器运行结果为
//1 2 3 0 0 0 0 0 0 0
//hehe

址传递方式

#include 
struct S
{int date[1000];char buf[100];
};
void print(struct S* ps)
{int i = 0;for (i = 0; i < 10; i++){printf("%d ", ps->date[i]);}printf("%s\n", ps->buf);
}
int main()
{struct S s = { {1,2,3},"hehe" };print(&s);return 0;
}
//------------------------
//编译器运行结果为
//1 2 3 0 0 0 0 0 0 0 hehe

结构体成员访问方法

结构体变量.结构体成员名
结构体指针->结构体成员名

传值调用和传址调用比较

传值调用:形参是实参的一份临时拷贝,如果实参占用的空间很大,那么形参占用的空间也很大。是一种空间上的浪费。

传址调用:只传过去了结构体变量的地址,所以优先选择传址调用。

函数传参的时候,参数是需要压栈的。

如果传递一个结构体对象的时候,结构体过大,参数压栈的的系统开销比较大,所以会导致性能的下降

结论:

结构体传参的时候,要传结构体变量的地址。

结语:
初阶结构体的东西就这么多,C语言初阶我们也算是基本介绍完了,接下来我们下一章会讲解C语言进阶的知识,欲知后事如何,请听下回讲解。

相关内容

热门资讯

linux入门---制作进度条 了解缓冲区 我们首先来看看下面的操作: 我们首先创建了一个文件并在这个文件里面添加了...
C++ 机房预约系统(六):学... 8、 学生模块 8.1 学生子菜单、登录和注销 实现步骤: 在Student.cpp的...
A.机器学习入门算法(三):基... 机器学习算法(三):K近邻(k-nearest neigh...
数字温湿度传感器DHT11模块... 模块实例https://blog.csdn.net/qq_38393591/article/deta...
有限元三角形单元的等效节点力 文章目录前言一、重新复习一下有限元三角形单元的理论1、三角形单元的形函数(Nÿ...
Redis 所有支持的数据结构... Redis 是一种开源的基于键值对存储的 NoSQL 数据库,支持多种数据结构。以下是...
win下pytorch安装—c... 安装目录一、cuda安装1.1、cuda版本选择1.2、下载安装二、cudnn安装三、pytorch...
MySQL基础-多表查询 文章目录MySQL基础-多表查询一、案例及引入1、基础概念2、笛卡尔积的理解二、多表查询的分类1、等...
keil调试专题篇 调试的前提是需要连接调试器比如STLINK。 然后点击菜单或者快捷图标均可进入调试模式。 如果前面...
MATLAB | 全网最详细网... 一篇超超超长,超超超全面网络图绘制教程,本篇基本能讲清楚所有绘制要点&#...
IHome主页 - 让你的浏览... 随着互联网的发展,人们越来越离不开浏览器了。每天上班、学习、娱乐,浏览器...
TCP 协议 一、TCP 协议概念 TCP即传输控制协议(Transmission Control ...
营业执照的经营范围有哪些 营业执照的经营范围有哪些 经营范围是指企业可以从事的生产经营与服务项目,是进行公司注册...
C++ 可变体(variant... 一、可变体(variant) 基础用法 Union的问题: 无法知道当前使用的类型是什...
血压计语音芯片,电子医疗设备声... 语音电子血压计是带有语音提示功能的电子血压计,测量前至测量结果全程语音播报࿰...
MySQL OCP888题解0... 文章目录1、原题1.1、英文原题1.2、答案2、题目解析2.1、题干解析2.2、选项解析3、知识点3...
【2023-Pytorch-检... (肆十二想说的一些话)Yolo这个系列我们已经更新了大概一年的时间,现在基本的流程也走走通了,包含数...
实战项目:保险行业用户分类 这里写目录标题1、项目介绍1.1 行业背景1.2 数据介绍2、代码实现导入数据探索数据处理列标签名异...
记录--我在前端干工地(thr... 这里给大家分享我在网上总结出来的一些知识,希望对大家有所帮助 前段时间接触了Th...
43 openEuler搭建A... 文章目录43 openEuler搭建Apache服务器-配置文件说明和管理模块43.1 配置文件说明...