C语言学习(十)结构体

目录

  • 一、结构体类型定义
  • 二、结构体变量的定义
  • 三、结构体变量赋值
      • 1. 定义结构体变量的同时进行赋值
      • 2. 定义结构体类型的同时定义变量并进行赋值
      • 3. 在定义结构体变量时对指定成员进行赋值
      • 4. 在定义完结构体变量后,通过'.'进行赋值
  • 四、结构体成员访问
  • 五、结构体内部指针的使用
  • 六、结构体指针传参
  • 七、结构体变量交换成员的值
      • 1. 单成员交换
      • 2. 所有成员交换
  • 八、结构体内部的结构体指针
      • 1. 栈区链表实现
      • 2. 堆区单链表
  • 九、结构体数组
  • 十、结构体指针数组
  • 十一、结构体内存大小
      • 1. 结构体对齐
      • 2. 结构体对齐的作用
      • 3. 结构体对齐的方式
  • 十二、结构体位域

结构体是一个构造类型,可以由不同类型的元素的成员组成。

结构体是一个类型,而非变量。
一般定义在全局,如果定义在函数中,只能在函数内部使用

一、结构体类型定义

struct <结构体名称>
{<变量类型1> <变量名1>;<变量类型2> <变量名2>;...<变量类型n> <变量名n>;
}; //分号不能省略

eg: 定义一个结构体

#include <stdio.h>struct Student{char name[128];int age;float sore;
};
  • 注:
    1. struct 是结构体的关键字,必须书写。
    1. 结构体名称可以省略,一般定义在结构体内部时使用这种方式,定义变量的方式略有不同。
    1. 结构体内部的成员是通过花括号来包括的
    1. 结构体类型的最后必须包括一个’;’
    1. 结构体内部的成员必须是确定大小的,所以结构体内部是不能写函数的。
    1. 结构体内部成员的数据类型可以相等,也可以不等
    1. 注意C语言中不能在定义结构体时在结构体内部进行赋值,即下面的定义是错误的
#include <stdio.h>
/***这种定义方法是错误的***/
struct Student{char name[128] = “lily”;int age = 10;float sore = 100;
};

二、结构体变量的定义

结构体变量定义:
struct <结构体名称> 标识符;结构体指针变量:
struct <结构体名称> *标识符;

三、结构体变量赋值

1. 定义结构体变量的同时进行赋值

struct Student s2 ={"xiao,18,99.9"};
//访问
printf("name:%s\n",s2.name);

2. 定义结构体类型的同时定义变量并进行赋值

struct Student{char name[128];int age;float sore;
}s1={"lily",17,99}; 

3. 在定义结构体变量时对指定成员进行赋值

struct Student{char name[128];int age;float sore;
}s1={.name="Lily"};
  • 注:不能写成下面的形式
/***错误的写法***/
struct Student{char name[128];int age;float sore;
}s1={s1.name="Lily"};//这种是错误的写法

4. 在定义完结构体变量后,通过’.'进行赋值

struct Student{char name[128];int age;float sore;
};int main()
{struct Student s1;strcpy(s1.name,"Lily");s1.age = 18;s1.sore = 99;
} 

四、结构体成员访问

结构体变量:
通过 <结构体变量>.<成员> 来访问

结构体指针:
*p . <成员>
p -> <成员>

eg :使用指针访问结构体的值,实现两个虚数相加。

#include <stdio.h>struct vir 
{int x;int y;
}s1={12,3},s2={65,32},s3; 
//此时s1,s2,s3均为全局变量
//他们的成员也都是全局变量,存储在常量区的.bss段和.data段int main(int argc, const char *argv[])
{struct vir *p1 = &s1;struct vir *p2 = &s2;struct vir *p3 = &s3;p3->x=(p1->x)+(p2->x);p3->y=(p1->y)+(p2->y);printf("s1+s2=%d+%d*i\n",p3->x,p3->y);p3->x=(p1->x)-(p2->x);p3->y=(p1->y)-(p2->y);printf("s1-s2=%d+%d*i\n",p3->x,p3->y);                                                                                                                     return 0;
}

五、结构体内部指针的使用

在这里插入图片描述

#include <stdio.h>
#include <stdlib.h>
struct Place
{int *arr;int size;int capacity;
};
int main()
{struct Place t;t.arr=(int *)malloc(4*50);//申请50个int型数据的空间大小t.size = 0;//相当于下标t.capacity = 50;//可以容纳的数据的个数
}

六、结构体指针传参

eg:在堆区申请一段地址连续的空间
create函数,申请一块空间
write函数,向申请的空间内写值

#include <stdio.h>
#include <stdlib.h>//定义结构体类型
typedef struct Place{int* arr;int size;int capacity;
}Place_t;//创建空间
int create(Place_t *s,int size)
{if(!p){printf("struct is empty!\n");return -1;}s->arr = (int *)malloc(4*size);if(!(s->arr)){printf("create fail!\n");return -1;}s->size=0;s->capacity=size;printf("create %d please success!\n",size);return 0;
}
//向空间中写值
int write(Place_t *s,int num)
{if(!p){printf("struct is empty!\n");return -1;}if((s->size)<=(s->capacity)){   *((s->arr)+(s->size)) = num;(s->size)++;}else{   printf("capacity is full!\n");return -1;                                                                                                                                                                                                   }   return 0;
}int main(int argc, const char *argv[])
{Place_t a;int size;int num;printf("请输入需要多少空间:");scanf("%d",&size);  create(&a,size);for(int i=0;i<size;i++){   printf("please input %d number:",i);scanf("%d",&num);if(write(&a,num)){printf("write fail!\n");}}for(int i=0;i<size;i++){printf("%d\n",*(a.arr+i));}//释放内存free(a.arr);a.arr=NULL;return 0;
}  

七、结构体变量交换成员的值

1. 单成员交换

#include <stdio.h>
#include <string.h>struct Cat_t
{char name[128];int age;
};  int main()
{struct Cat_t c1 = {"mimi",1};struct Cat_t c2 = {"huahua",2};printf("交换前:\nc1.name=%s,c1.age=%d;\nc2=%s,c2.age=%d\n",c1.name,c1.age,c2.name,c2.age);struct Cat_t ret;strcpy(ret.name,c1.name);strcpy(c1.name,c2.name);strcpy(c2.name,ret.name); printf("交换后:\nc1.name=%s,c1.age=%d;\nc2=%s,c2.age=%d\n",c1.name,c1.age,c2.name,c2.age); return 0;
}  

输出结果:
在这里插入图片描述

2. 所有成员交换

#include <stdio.h>struct Cat_t
{char name[128];int age;
};  int main()
{struct Cat_t c1 = {"mimi",1};struct Cat_t c2 = {"huahua",2};printf("交换前:\nc1.name=%s,c1.age=%d;\nc2=%s,c2.age=%d\n",c1.name,c1.age,c2.name,c2.age);struct Cat_t ret;ret = c1;c1 = c2;c2 = ret;printf("交换后:\nc1.name=%s,c1.age=%d;\nc2=%s,c2.age=%d\n",c1.name,c1.age,c2.name,c2.age);return 0;
}  

输出结果:
在这里插入图片描述

八、结构体内部的结构体指针

1. 栈区链表实现

#include <stdio.h>typedef struct Node
{int number;struct Node* next;
}Node_t, *Node_p;void show(Node_p p)
{while((p->next)!=NULL){printf("%d ",p->next->number);p = p->next;}putchar(10);
}int main(int argc, const char *argv[])
{Node_t head = {-1,NULL};Node_t n1 = {10,NULL};Node_t n2 = {20,NULL};head.next = &n1;n1.next = &n2;show(&head);return 0;
}   

输出结果:
在这里插入图片描述

2. 堆区单链表

#include <stdio.h>
#include <stdlib.h>typedef struct Node
{int number;struct Node* next;
}Node_t, *Node_p;int init(Node_p *phead); 
//创建头节点:头节点number赋值成-1;next赋值成NULL
int creat(Node_p head,int number);
//创建节点:先找到链表尾部,在尾部插入节点
void sfree(Node_p head);
//
void show(Node_p p);int main(int argc, const char *argv[])
{Node_p head;init(&head);creat(head,10);creat(head,20);creat(head,30);creat(head,40);show(head);sfree(head);return 0;
}int init(Node_p *phead)
{*phead = (Node_p)malloc(sizeof(Node_t));if(!(*phead)){return -1;}(*phead)->number = -1;                                                                                                                                                                                                                                                                                                     (*phead) -> next = NULL;return 0;
}int creat(Node_p head,int number)
{//在堆区申请一块空间Node_p ret = (Node_p)malloc(sizeof(Node_t));if(!ret)return -1;//给空间赋值ret -> number =number;ret -> next = NULL;Node_p tail = head;//链接while(tail->next){tail=tail->next;}tail->next = ret;return 0;   
}
//释放堆区空间
void sfree(Node_p head)
{Node_p ret;while(ret = head->next) {free(head);head = ret;}free(head);
}
//打印
void show(Node_p p)
{while((p->next)!=NULL){printf("%d ",p->next->number);p = p->next;}putchar(10);
}

关于释放空间的第二种思路:

void sfree(Node_p head)
{Node_p p;while(head -> next){p = head -> next;head -> next = p -> next;free(p);}free(head);
}

九、结构体数组

结构体数组的本质是一个数组,数组中的每一个值都是结构体。

struct <结构体名称> <标识符>[成员个数];

eg

#include <stdio.h>typedef struct Student
{char name[128];int age;float score;
}St_t,*St_p;int main(int argc, const char *argv[])
{St_t s1={"Lily",10,100.0};St_t s2={"LiMing",14,98.9};St_t s3={"Mary",9,97.5};St_t s4={"Bob",13,96.3};St_t s5={"Caily",11,120.0};St_t s_arr[5]={s1,s2,s3,s4,s5};for(int i=0;i<5;i++){   printf("%d:name=%s,age=%d,sore=%.2f\n",i,s_arr[i].name,s_arr[i].age,s_arr[i].score);                                                                                                                         }   return 0;
}

十、结构体指针数组

结构体指针数组本质是一个数组,数组中的每一个元素都是结构体指针。
eg:

struct <结构体名称> *<标识符>[成员个数];

eg

#include <stdio.h>typedef struct Student
{char name[128];int age;float score;
}St_t,*St_p;int main(int argc, const char *argv[])
{St_t s1={"Lily",10,100.0};St_t s2={"LiMing",14,98.9};St_t s3={"Mary",9,97.5};St_t s4={"Bob",13,96.3};St_t s5={"Caliy",11,120.0};St_p arr[5]={&s1,&s2,&s3,&s4,&s5};for(int i=0;i<5;i++){   printf("%d:name=%s,age=%d,sore=%.2f\n",i,arr[i]->name,arr[i]->age,arr[i]->score);}   return 0;
}

十一、结构体内存大小

1. 结构体对齐

结构体的整个大小并不是所有成员依次加起来的大小,因为会发生结构体对齐

2. 结构体对齐的作用

CPU不是按照字节大小进行取值的,而是按块(一般是四字节)进行取值。
为了使计算机更快地进行取值,所以结构体内部成员要对齐。

3. 结构体对齐的方式

结构体的第一个成员存放在结构体变量的0地址处。

其他成员存放在该成员的对齐数的整数倍的位置上。
对齐数:该成员的大小和编译器设置的最大对齐数的整数中的最小值。
(Linux中没有设置最大对齐数,windows默认对齐数是8)

结构体的整体大小,是这个结构体的所有成员的最大对齐数的整数倍。

  • 注:
  • 如果结构体的成员中有数组,则按数组的每个元素的大小作为对齐数。
  • 如果结构体的成员中有结构体,先将结构体内部成员对齐,再整体对齐,同样按照上面的规则计算。

eg

#include <stdio.h>struct Person 
{char name[3];int age;
}; //8struct A
{int a;struct Person boy;;
};//12struct B
{int a;double b;char c;
}; //24struct C 
{int a; char arr[20];int b; 
};//28struct D 
{double a;char b;double c;struct E{int o1;char [5];};//12
};//24+12=36,整体对齐:最大对齐数是8,因此是40

十二、结构体位域

结构体位域本质上是压缩内存的一种方式。一般是unsigned int、char类型使用。

eg

struct A
{unsigned int a:10; //使用了int的10位unsigned int b:5;//如果存不下,会只取后五位
}struct A n;

此时结构体n占用的字节数就是4。一个int型空间就可以容纳。
a占10位,b占5位。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/836771.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

MYSQL:MySQL 事务隔离级别详解

一、MySQL事务是什么&#xff1f; MySQL事务是一组在数据库中执行的操作&#xff0c;这些操作要么全部成功执行&#xff0c;要么全部不执行&#xff0c;以确保数据库的完整性和一致性。 事务的 ACID 事务具有四个特征&#xff1a;原子性&#xff08; Atomicity &#xff09;、…

用Robotframework+selenium 进行webui页面自动化测试

Robotframework其实就是一个自动化的框架&#xff0c;想要进行什么样的自动化测试&#xff0c;就需要在这框架上添加相应的库文件&#xff0c;而用于webui页面自动化测试的就是selenium库. ​ 关于robotframework框架的搭建我这里就不说了&#xff0c;今天就给大家根据一个登录…

HarmonyOS开发案例:【Stage模型下Ability的创建和使用】

介绍 基于Stage模型&#xff0c;对Ability的创建和使用进行讲解。首先在课程中我们将带领大家使用DevEco Studio创建一个Stage模型Ability&#xff0c;并使用UIAbilityContext启动另一个Ability&#xff0c;然后借助Want&#xff0c;在Ability之间传递参数&#xff0c;最后我们…

【深度学习】最强算法之:Word2Vec

Word2Vec 1、引言2、Word2Vec2.1 定义2.2 原理2.3 实现方式2.4 算法公式2.5 代码示例 3、总结 1、引言 小屌丝&#xff1a;鱼哥&#xff0c; help ,help 小鱼&#xff1a; 你这是在鱼塘里面无法呼吸了&#xff1f; 小屌丝&#xff1a;… 别闹&#xff0c;鱼哥&#xff0c; 小鱼…

Dread Hunger 海上狼人杀服务器开服教程

1、购买后登录服务器&#xff0c;百度莱卡云 1.1、第一次购买服务器会安装游戏端&#xff0c;大约5分钟左右&#xff0c;如果长时间处于安装状态请联系客服 2、创建端口 点击网络创建第二个端口作为副端口&#xff08;副端口的作用是用于第二局游戏&#xff0c;因为游戏BUG&am…

Unity导出的webgl包在浏览器下报错:Unable to parse Build/导出的项目名称.framework.js.gz

先根据链接Unity WebGL项目打包后本地打开报错问题解决方法_unity 打包webgl报错:webassembly.instantiate()-CSDN博客文档操作一番后,在360极速里面兼容模式——黑屏如图: 极速模式:进度条走不满,在谷歌浏览器里面的红色报错文字不出现。 然后打开谷歌浏览器,报如下错:…

如何把握人力RPO的蓝海机遇?实战策略分享!

随着企业间竞争的日益激烈&#xff0c;人力资源管理的重要性愈发凸显。在众多人力资源管理策略中&#xff0c;招聘流程外包(RPO)作为一种新兴的服务模式&#xff0c;逐渐受到业界的关注。那么&#xff0c;人力RPO是否是蓝海项目?我们又该如何实施RPO呢? 一、人力RPO&#xff…

企业微信创建应用(一)

登录到企业微信后台管理(https://work.weixin.qq.com/)进入自建应用(应用管理-应用-创建应用) 3.查看参数AgentId和 Secret 4.企业微信查看效果

极氪速度:70亿市值登陆纽交所,这家纯电豪华品牌开启弹射模式

作者 |老缅 编辑 |德新 北京时间5月10日晚&#xff0c;极氪智能科技在美国纽交所挂牌上市&#xff0c;股票代码为「ZK」。 因获超额认购&#xff0c;极氪扩大了IPO规模&#xff0c;以每股21美元的价格累计发行2100万股美国存托股票&#xff08;每份ADS 对应 10 份普通股&…

【人民网注册_登录安全分析报告】

前言 由于网站注册入口容易被黑客攻击&#xff0c;存在如下安全问题&#xff1a; 暴力破解密码&#xff0c;造成用户信息泄露短信盗刷的安全问题&#xff0c;影响业务及导致用户投诉带来经济损失&#xff0c;尤其是后付费客户&#xff0c;风险巨大&#xff0c;造成亏损无底洞 …

能聚合各站热点的DailyHot

什么是 DailyHot ? 今日热榜&#xff08;DailyHot&#xff09;是一个获取各大热门网站热门头条的聚合网站&#xff0c;能追踪全网热点、实现简单高效阅读。项目分为前、后端&#xff0c;其中后端提供了一个聚合热门数据的 API 接口。 &#x1f6a9; 后端 API 特性 极快响应&a…

中仕公考:应届生身份是怎样界定的?

应届毕业生指在应该毕业的年份即将毕业或者已经毕业学生&#xff0c;应届生参加公务员考试有更大的优势&#xff0c;部分岗位也只对应届生开放。 对应届毕业生的界定&#xff1a; 国家统一招生的高校毕业生离校时和在择业期内未落实工作单位&#xff0c;其户口、档案、组织关…

# 从浅入深 学习 SpringCloud 微服务架构(十七)--Spring Cloud config(2)

从浅入深 学习 SpringCloud 微服务架构&#xff08;十七&#xff09;–Spring Cloud config&#xff08;2&#xff09; 一、springcloudConfig 入门案例&#xff1a;搭建 config 服务端 1、登录 码云&#xff1a;https://gitee.com/ 1&#xff09;点击右上角 【】 再点击【新…

Java | Leetcode Java题解之第73题矩阵置零

题目&#xff1a; 题解&#xff1a; class Solution {public void setZeroes(int[][] matrix) {int m matrix.length, n matrix[0].length;boolean flagCol0 false;for (int i 0; i < m; i) {if (matrix[i][0] 0) {flagCol0 true;}for (int j 1; j < n; j) {if (…

浮点数的由来及运算解析

数学是自然科学的皇后&#xff0c;计算机的设计初衷是科学计算。计算机的最基本功能是需要存储整数、实数&#xff0c;及对整数和实数进行算术四则运算。 但是在计算机从业者的眼中&#xff0c;我们知道的数学相关的基本数据类型通常是整型、浮点型、布尔型。整型又分为int8&a…

Kerberos修改协议为TCP

部署前 修改模板/home/cloud-setup/deploy-forklift/mids/forklift-basic/kde/v1.0/impl/plays/roles/krb5-client/templates/krb5.conf.j2 添加如下参数 udp_preference_limit 1 部署后 界面修改 添加如下参数&#xff0c;并勾选下发配置按钮&#xff0c;重启刷新服务

Linux防火墙iptalbes

1 iptalbes 1.1 概念 防火墙(Firewall)是一种隔离技术&#xff0c;用于安全管理与筛选的软件和硬件设备&#xff0c;使计算机内网和外网分开&#xff0c;可以防止外部网络用户以非法手段通过外部网络进入内部网络&#xff0c;保护内网免受外部非法用户的侵入。 1.2 SELinux …

pywinauto,一款Win自动化利器!

pywinauto&#xff0c;一款Win自动化利器&#xff01; 1.安装 pywinauto是一个用于自动化Python模块&#xff0c;适合Windows系统的软件&#xff08;GUI&#xff09;&#xff0c;可以通过Pywinauto遍历窗口&#xff08;对话框&#xff09;和窗口里的控件&#xff0c;也可以控…

前端动态旋转地球背景

效果图 贴下源码 <template><div class"map-bg"><div class"canvas" id"canvs"></div><canvas class"canvasxk" id"canv"></canvas></div> </template><script setup …

栈的实现与OJ括号匹配

今日备忘录: "不破不立. " 本文索引 1. 前言2. 顺序表与链表的区别3. 什么是栈4. 栈的实现5. OJ括号匹配6. 总结 1. 前言 人总是在坍塌中重建, 有些东西必须摧毁, 才能迎来新生, 不管是那些消耗你的人, 还是令你感到焦虑的事情, 还是一份你觉得毫无意义并且又不喜欢…