C语言 结构体

article/2025/9/18 23:32:31

1什么是结构体

结构体是一种集合,它里面包含了多个变量或数组,它们的类型可以相同,也可以不同,每个这样的变量或数组都称为结构体的成员。结构的成员可以是标量、数组、指针,甚至是其他结构体。

2结构体的定义

(1)定义结构体的一般格式:

struct 结构名
{
类型 变量名;
类型 变量名;
...
} 结构变量;

例如定一个学生的结构体
struct student{
char no[20]; //学号
char name[20]; //姓名
char sex[5]; //性别
int age; //年龄
}stu[100];

像上面这里,我们就定义了表示100个学生的结构体。如果没有结构体,我们可能要用400行代码才能表示完100个学生的信息。这就是结构体的好处。
注意:结构体变量可以写,也可以不写,但是后面的分号不能省略
(2)结构体定义的特殊格式
匿名结构体(没有结构名),它只能使用一次,用过一次就不能再用了

struct 
{
类型 变量名;
类型 变量名;
...
} 结构变量;

看下面

代码1
struct {
char b;      
char name[20];        
int a;         
}x;代码2
struct {
char b;      
char name[20];        
int a;         
}a[10],*p;

既然代码1和代码2的结构体成员一样,那我是不是可以把变量x的地址放到*p中去呢?就像这样 p=&x,可行吗?
实际上不可以。因为匿名结构体的成员虽然一样,但是在编译器看来,他们的类型是不一样的,所以编译器会报错(不兼容)。

3结构体变量的初始化

(1)方法:在对结构体变量初始化时,要对结构体成员一 一赋值,不能跳过前面成员变量,而直接给后面成员赋初值,但是可以只赋值前面几个,对与后面未赋值的变量,如果是数值型,则会自动赋值为0,对于字符型,会自动赋初值为NULL,即‘\0’
(2)定义时直接赋值

struct student{     
char name[20];      
char sex;  
int num;         
}x={"zhangsan",'m',1234};
或者
struct student{     
char name[20];  
char sex;      
int num;         
}struct student s={"zhangsan",'m'}

//需要注意的是,字符用’ ’ ,而字符串要用" "
(3)定义结构体后逐个赋值
按顺序

struct student{     
char name[20];  
char sex;      
int num;         
}stu;
int main()
{
stu.name="zhangsan";
stu.sex='m';
stu.num=1234;
return 0;
}

(4)定义之后任意赋值
可以不按顺序

struct student{     
char name[20];  
char sex;      
int num;         
}stu1;
int main()
{
.sex='m'; //或者stu1.sex='m'
.num=1234; //stu1.num=1234
.name="zhangsan";
return 0;
}

**知识:**利用成员运算符进行初始化,在结构体变量内部,在成员运算符“ . ”前面加或者不加结构体变量名都是可以的。

4结构体成员的访问

结构体成员访问操作符有 " . "和 “->”

(1) 用“ . ”访问

4.1一般的结构体成员输出

#include<stdio.h>
struct student{char name[20];char sex;int num;
};
int main()
{struct student s = { "zhangsan", 'm', 123 };//比如现在要将结构体的成员打印出来printf("%s\n", s.name);printf("%c\n", s.sex);printf("%d\n", s.num);return 0;
}

在这里插入图片描述
4.2结构体中又有结构体
需要一级一级访问,直到最后一级的成员

struct in{int a=10;int b=20;
};
struct student{char name[20];char sex;int num;struct in s1;
};
int main()
{struct student s = { "zhangsan", 'm', 123 };//比如现在要将结构体的成员打印出来printf("%s\n", s.name);printf("%c\n", s.sex);printf("%d\n", s.num);printf("%d\n", s.s1.a);//变量s指向s1再指向aprintf("%d\n", s.s1.b);//变量s指向s1再指向breturn 0;
}

在这里插入图片描述

**

(2)用 -> 访问

**
成员变量为指针(不管指向什么,包括结构体)
把这部分内容放在下文(7结构体的传参)讲

5结构体的解引用

结构体的自引用(self reference),就是在结构体内部,包含指向(需要用指针)自身类型结构体的指针。
5.1错误的方式:

 struct tag_1{struct tag_1 A; int value;};

这种声明是错误的,因为这种声明实际上是一个无限循环,成员struct tag_1 A 是一个结构体,struct tag_1 A 的内部还会有成员是结构体,依次下去,无线循环。在分配内存的时候,由于无限嵌套,也无法确定这个结构体的长度,所以这种方式是非法的。
5.2正确的方式(使用指针):

struct tag_1{struct tag_1 *A; /* 指针 */int value;};

由于指针的长度是确定的(在32位机器上指针长度为4),所以编译器能够确定该结构体的长度。

6.typedef

typedef是类型重命名,将结构体重新命名为一个新的名字

typedef struct tag{int num; char name;}node;

就相当于将结构体重新命名为node
下面如果我们要创建两个变量n1和n2,可不可以像下面这样写呢?

typedef struct tag{int num; char name;}node;
int main()
{struct tag n1;node n2;return 0;
}

这样写也是对的,node n2就相当于 struct tag n2,因为typedef将strcut tag 重命名成了node。此时n1和n2的类型是一样的。

typedef的好处就是可以将复杂的结构体重命名为一个简单的名字,方便我们创建新的变量。

7结构体的传参

一是传递结构体变量,这是值传递;二是传递结构体指针,这是地址传递
比如我们现在需要 设计一个函数,用来打印结构体成员
方法1传值

#include<stdio.h>
struct stu{char name[20];char sex;int num;
};
void print(struct stu p) 
{   //用来打印结构体成员的函数printf("%s\n", p.name); printf("%c\n", p.sex);   printf("%d\n", p.num);   
}
int main()
{struct stu s1 = { "zhangsan", 'm', 1234 };print(s1);  //把变量s1的值传过去return 0;
}

在这里插入图片描述

方法2传址

struct stu{char name[20];char sex;int num;
};
void print2(struct stu* p2)  //用一个指针p2,来接收结构体s2的地址
{   //用来打印结构体成员的函数printf("%s\n", p2->name);  //p2指向nameprintf("%c\n", p2->sex);   //p2指向sexprintf("%d\n", p2->num);   //p2指向num
}
int main()
{struct stu s2 = { "zhangsan", 'm', 1234 };print2(&s2);  //把s2的地址传过去return 0;

在这里插入图片描述

8结构体内存对齐

比如我们现在要计算结构体的大小

struct s1{
char c1;
int a;
char c2;
}s1;
struct s2{
char c1;
char c2;
int i;
}s2;
int main()
{
printf("%d",sizeof(s1));
printf("%d",sizeof(s2));
return 0;
}

在这里插入图片描述
为什么两个成员一样的结构体,大小却不一样?这是因为两个结构体的内存对齐不一样导致的
7.1内存对齐规则
(1)第一个成员在结构体变量偏移量为0 的地址处。
(2)其他成员变量要对齐到某个数字(对齐数)的整数倍的地址处。对齐数 = 编译器默认的一个对齐数该成员大小中的较小值。vs中默认值是8 Linux默认值为0(vs:64位编译系统下是8个字节,32位编译系统下是4个字节)。
(3)结构体总大小为最大对齐数的整数倍。(每个成员变量都有自己的对齐数)
(4)如果嵌套结构体,嵌套的结构体对齐到自己的最大对齐数的整数倍处,结构体的整体大小就是所有最大对齐数(包含嵌套结构体的对齐数)的整数倍。

我们再来看看s1和s2的内存对齐
在这里插入图片描述

在这里插入图片描述

补充说明,int a和int i的对齐数都是4,所以偏移量从他们的整数倍开始
7.2为什么存在内存对齐呢?
平台原因(移植原因):
不是所有的硬件平台都能访问任意地址的任意数据的;某些平台只能在某些地址处取某些特定类型的数据
性能原因
数据结构尤其是栈应该尽可能在自然边界上对齐。原因在于,为了访问未对齐的内存,处理器需要做两次访问内存;而对齐的内存访问仅需要一次访问。
缺点:
无可厚非:这必然会存在效率问题,这是一种以空间换时间的做法,虽然浪费了一定的空间,但是却可以少花时间,所以这种做法是值得的
在这里插入图片描述


http://chatgpt.dhexx.cn/article/Qqu365mi.shtml

相关文章

c语言:结构体(详解)

初识结构体 一.结构体声明1.结构体的概念2.声明 二.结构体的基础使用三.结构体变量的定义和初始化四.空结构体五.柔性数组1.定义2.使用 六.结构体内存对齐七.位端 一.结构体声明 1.结构体的概念 结构体是一些值的集合&#xff0c;这些值称为成员变量。结构的每个成员可以是不同…

C语言结构体详解

目录 一、结构体的基本概念 举个例子 二、结构体变量 三、结构体占用的内存情况 举个例子 运行效果 再次运行 四、结构体的变量名 五、结构体初始化 五、结构体初始化 举个例子 运行效果 六、结构体成员的访问 举个例子 运行效果 八、结构体指针 举个例子 运行效…

C语言结构体超详解(小白一看就懂,多维度分析!!!!)

目录 一、前言 二、结构体详解 &#x1f350;什么是结构体 &#x1f34e;结构体的定义与基础结构 &#x1f351;结构体的使用 &#x1f4a6;结构体的初始化 &#x1f4a6;结构体的成员访问 &#x1f4a6;结构体数组 &#x1f4a6;结构体指针--------------指向结构体变…

C语言之结构体(进阶篇)

目录 1.结构体的内存对齐​ 如何计算呢&#xff1f;​ 掌握结构体的对齐规则&#xff1a; 为什么存在内存对齐呢&#xff1f;​ ​​​​​​​offsetof​ 位段​ 什么是位段&#xff1f;​ 比如&#xff1a; 位段的内存分配​ 举个例子 位段的跨平台问题&#xff1a;​ 枚举…

C语言——结构体(全)

目录 一、结构体的设计 二、结构体变量的初始化 2.1结构体在内存表示&#xff1b; 2.2结构体初始化&#xff1b; 2.3结构体指针变量 2.4结构体嵌套结构体 三、结构体成员访问 3.1、结构体成员访问 3.2、结构体变量和指针 ​3.3、结构体和函数 四、结构体与数组 五、…

Github客户端下载慢的解决方法

Github客户端下载慢的解决方法 Github客户端下载解决方法获取下载连接 Github客户端下载 Github客户端的下载地址是——Github客户端下载。 但是下载速度特别慢&#xff0c;最快也就十几K。 解决方法 使用迅雷下载&#xff1a;将Github客户端的下载地址复制到迅雷中&#…

windows平台下使用Github(2 创建代码仓库,安装Github客户端.)

本文会分章节的来介绍如何在windows平台下使用GitHub 一、注册Github账号 查看 二、创建代码仓库&#xff0c;安装Github客户端.查看 三、Github上传和下载(1 客户端方式)查看 四、Github上传和下载(2 命令行方式)查看 1、创建一个代码托管仓库。 点击右上角的 号或者点…

github客户端进行token认证

从 2021 年 8 月 13 日起&#xff0c;GitHub 在对 Git 操作进行身份验证时不再接受帐户密码。您需要添加 PAT&#xff08;个人访问令牌&#xff09;&#xff0c;您可以按照以下方法在您的系统上添加 PAT。 git - Support for password authentication was removed. Please us…

【解决】GitHub 客户端下载后安装在哪里?

GitHub Desktop 配置环境变量GitHub 安装路径GitHub Shell、Bash 环境是 Windows 10。 从 GitHub 官网下载了 GitHub 的 Desktop 版本之后&#xff0c;它其实不仅是一个 GUI&#xff0c;还带了 Shell&#xff08;Bash&#xff09;&#xff0c;但是发现找不到它们是被安装在哪个…

GitHub客户端上传本地代码

创建GitHub账号、安装GitHub客户端登录GitHub网站、在客户端登录账户创建新的代码存放处 填写及勾选一些信息 复制此代码存放处的路径 利用客户端上传代码 第一步&#xff1a;点击第五步的Open in Desktop&#xff0c;打开本地客户端 第二步&#xff1a;点击下图蓝色选中选…

你们心心念念的 GitHub 客户端终于来了!

点击上方 "程序员小乐"关注, 星标或置顶一起成长 每天凌晨00点00分, 第一时间与你相约 每日英文 For something,we cant understand when we are young but by the time we understand,we are no longer young. 有些事情&#xff0c;当我们年轻的时候无法懂得&#x…

GitHub客户端的使用方法

一&#xff1a;创建自己的GitHub账号 GitHub官网链接 https://github.com/ 自行创建账号&#xff0c;因本文主要介绍GitHub客户端的使用方法&#xff0c;所以注册账号略 二&#xff1a;下载GitHub客户端 GitHub客户端下载的官网链接 https://desktop.github.com/ 下载完成之…

gitHub客户端的安装与使用总结

一、第一步 注册github账号 1.注册界面 https://github.com/&#xff0c;如下图&#xff1a; 2.下注册流程 3.上面简单的输入一下用户名、邮箱地址、密码点击创建即可&#xff0c;进入下一步&#xff0c;如下图&#xff1a; 如果勾选了“Help me set up an organization next”…

Github客户端安装使用教程(一)

转载请注明出处&#xff0c;http://blog.csdn.net/bule_zst/article/details/74185268 1. 下载安装 下载地址 下载好后双击运行&#xff0c;这个安装程序比较奇葩&#xff0c;是强制安装路径的&#xff0c;运行后什么界面都没有&#xff0c;后台安装&#xff0c;大概等到你觉…

GitHub Windows 客户端使用教程

GitHub Desktop tutorial 一、前期准备 下载安装 GitHub Windows 客户端&#xff0c;链接在这里。 二、登录账号 在客户端登录自己的 GitHub 账号。 三、选择要上传的 repository 进行 Clone 比如我 Clone 了 LeetCode-Solutions。 然后选择 URL 进行 Clone 。 进入主界面…

github客户端教程

在网上搜索了下github的教程,都是讲的用命令行去提交代码的,真心不想这么麻烦,都有客户端了,还去这么麻烦,程序员还要着干嘛呢.于是网上找了一份客户端的教程,转载过来. 一&#xff1a;下载GitHub for Windows 2.0 下载地址&#xff1a;https://windows.github.com/ 二&#xf…

github客户端使用

用github windows离线版安装好之后&#xff08;需要安装的请留邮箱&#xff09;。安装好之后桌面呈现 点击左侧图标进入客户端&#xff0c;进入登录界面如下图 输入帐号密码登录&#xff0c;如果没有去官网申请一个。 登录之后&#xff0c;先进行第一步&#xff0c;新建…

github客户端的下载

在github官网上&#xff0c;下载客户端完成后&#xff0c;安装时还需要下载一些文件。但是我之前安装了很多次&#xff0c;都是下载了20多M就停止了&#xff0c;提示下载终止。之后就只能从开始下载&#xff0c;一直安装不成功。一直停留了2周时间&#xff0c;期间也在网上搜过…

新手使用GitHub客户端提交本地项目到GitHub网站详细步骤

1.下载https://windows.github.com/ github客户端 2.安装完github&#xff0c;会出现 点击GitHub&#xff0c;Git Shell是命令行指令&#xff0c;暂时用不上 3.点击进入之后 输入你在https://github.com上面注册的用户名和密码点击log in 4.登录之后新建项目 点击左上角…

新版GitHub客户端上传文件夹教程笔记

新版GitHub客户端上传文件夹教程笔记 文章目录 新版GitHub客户端上传文件夹教程笔记前言&#xff1a;上传文件夹步骤&#xff1a; 前言&#xff1a; 相信很多人和我一样&#xff0c;用GitHub的目的就是上传一下自己的代码&#xff0c;并不想学什么花里胡哨的命令行操作&#x…