一篇文章带你用C语言玩转结构体

目录
  • 前言
  • 一、结构体的声明与定义
    • 1.结构体的声明
    • 2.结构成员的类型
    • 3.结构体的定义
  • 二、初始化结构体
  • 三、访问结构体成员
  • 四、结构体嵌套
  • 五、结构体指针
  • 六、结构体传参
  • 总结

前言

C语言提供了不同的数据类型,比如说int、float、double、char等,不同的类型决定了一个变量在内存中应该占据的空间以及表现形式。

但是,当我们定义一个人的时候,人的不同属性就比较难用同一个数据类型来定义了,因为人的身高、年龄、体重等属性往往需要不同数据类型,在这个时候,我们便引入结构体这个概念。

一、结构体的声明与定义

1.结构体的声明

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

当我们面对的事物有多个不同的数据类型的时候,我们就可以使用结构体来组织了。

比如说,一本书有书名、作者、售价、出版日期等等不同的数据类型,这时候我们可以创建结构体来包含书的不同数据类型。

而结构体声明是描述结构体组合的主要方法,语法格式为:

struct 结构体名称
{
结构体成员1;
结构体成员2;
结构体成员3;

};//分号不能丢

【注意】

结构体成员既可以是任何一种基本的数据类型,也可以是另一种结构体,如果是后者就相当于结构体的嵌套。(俗称套娃)

例如:

struct Book//描述一本书的相关属性,其中Book是这个框架的名称
{
	char name[20];//书名
	char author[20];//作者
	float price;//价格
};//分号一定不能丢

这样就相当于描述了一本书的框架。

2.结构成员的类型

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

3.结构体的定义

结构体的声明只是进行一个简单的描述,实际上在没有定义结构体类型变量之前,它是不会在内存中分配空间的。

也就是说,它还没有被真正使用,虚拟存在,只有定义了结构体类型变量,才真实存在。

举个例子,上面定义了书的框架

struct Book//描述一本书的相关属性,其中Book是这个框架的名称
{
	char name[20];//书名
	char author[20];//作者
	float price;//价格
};//分号一定不能丢

这里在编译器中,并不会分配内存空间,它仅仅是虚拟存在。而一旦我们定义了结构体类型变量,它就可以被分配空间了。

比如:

struct Book//描述一本书的相关属性,其中Book是这个框架的名称
{
	char name[20];//书名
	char author[20];//作者
	float price;//价格
};//分号一定不能丢
int main()
{
	struct Book book;//局部变量--放在栈区
	return 0;
}

我们在上面例子中也可以注意到,定义结构体变量的语法是:

struct 结构体名称 结构体变量名

此外,还可以在结构体声明的时候定义结构体变量

struct Book//描述一本书的相关属性
{
	char name[20];
	char author[20];
	float price;
}b1,b2;//b1,b2是全局变量。放在静态区
int main()
{
	struct Book book;//局部变量--放在栈区
	return 0;
}

b1、b2结构体变量是一个全局变量,在其他函数中也可以对它进行访问。

二、初始化结构体

我们在定义一个变量或数组的时候可以对其进行初始化,

例如:

int a=10;
int arr[10]={1,2,3,4,5,6,7,8,9,0};

同理,定义结构体变量的时候,我们也可以同时为其初始化

struct Book//描述一本书的相关属性
{
	char name[20];
	char author[20];
	float price;
}b1,b2;//b1,b2是全局变量。放在静态区
int main()
{
	struct Book book=
	{
	"《笑傲江湖》","金庸",30
	};//这样的话,就将结构体变量初始化了,也就是定义变量的同时赋初值
	return 0;
}

三、访问结构体成员

结构体变量访问成员 结构变量的成员是通过点操作符(.)访问的。点操作符接受两个操作数。

比如,book.name就是引用book结构体变量的name成员,它是一个字符数组。

#include <stdio.h>
struct Book//描述一本书的相关属性
{
	char name[20];
	char author[20];
	float price;
}b1, b2;//b1,b2是全局变量。放在静态区
int main()
{
	struct Book book=
	{
		"《笑傲江湖》", "金庸", 30
	};//这样的话,就将结构体变量初始化了,也就是定义变量的同时赋初值
	printf("%s %s %f\n", book.name, book.author, book.price);
//用. 来访问
	return 0;
}

四、结构体嵌套

如果访问嵌套的结构体成员的话,就需要使用多层点号运算符来进行操作。因为C语言的结构体只能对最底层的成员进行访问,如果存在多级结构体嵌套的话,就需要一级一级地深入,直到找到最底层的成员才行

struct S
{
	int a;
	char c;
	double d;
};
struct T
{
	struct S s;//结构体嵌套
	char name[20];
	int num;
};
int main()
{
	struct T t = { {100,'c',3.14},"里斯",30 };
	printf("%d %c %f %s %d\n", t.s.a, t.s.c, t.s.d, t.name, t.num);//使用了两层点号运算符寻找成员
	return 0;
}

五、结构体指针

在开头的时候说过,结构的成员可以是标量、数组、指针。

在这里,我们来认识一下结构体指针。

struct Book *pt;

这里声明了一个指向Book结构体类型的指针变量pt

struct S
{
	int a;
	char c;
	double d;
};
struct T
{
	struct S s;
	char name[20];
	int num;
};
int main()
{
	struct T t = { {100,'c',3.14},"里斯",30 };
	printf("%d %c %f %s %d\n", t.s.a, t.s.c, t.s.d, t.name, t.num);
	struct T*pt = &t;//拿到地址的方式
	printf("%d %c %f %s %d\n", (*pt).s.a, (*pt).s.c, (*pt).s.d, (*pt).name, (*pt).num);
	printf("%d %c %f %s %d\n",pt->s.a,pt->s.c,pt->s.d,pt->name,pt->num);
	return 0;
}

【注意】数组名指向的是第一个元素的地址,所以可以直接将数组名赋值给指针变量。但是结构体变量的变量名并不是指向该结构体的地址,所以要使用取地址运算符(&)才能获取其地址。

如上面的:

struct T*pt = &t;//拿到地址的方式

通过上面的例子我们也可以发现,通过结构体指针访问结构体成员有以下两种方法:

(1)(*结构体指针).成员名
(2)结构体指针->成员名

第一种由于点号运算符(.)比指针的取值运算符(*)优先级高,所以要使用小口号先对指针进行解引用,让它变成该结构体变量,再用点运算符取访问其成员。

以上两种方法在实现的时候完全等价。但是,切记,点号(.)只能用于结构体,而箭头(->)只能用于结构体指针。

【打印结果一样】

当二者皆可用的时候,优先采用第二种方法,因为箭头具有指向性,很直观的就可以把它与指针联系起来了。

六、结构体传参

函数调用的时候,参数的传递就是值传递的过程,也就是将实参传给形参的过程。所以,结构体变量可以作为函数的参数传递,两个相同结构体类型的结构体变量也支持直接赋值。

struct S
{
	int arr[100];
	int num;
	char ch;
	double d;
};
//结构体传参
void print1(struct S ss)
{
	printf("%d %d %d %c %1f", ss.arr[0],ss.arr[2],ss.num,ss.ch,ss.d);
}
//结构体地址传参
void print2(struct S*ps)
{
	printf("%d %d %d %c %1f", ps->arr[0], ps->arr[2], ps->num, ps->ch, ps->d);
}
int main()
{
	struct S s = { {1,2,3,4,5}, 100, 'w',3.14  };
	print1(s);//传结构体
	print2(&s);//传地址
	return 0;
}

可以看到,确实把参数传递过去了。

那么,上面的 print1 和 print2 函数哪个好些?

答案是:首选print2函数。 原因:

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

因此,结构体传参的时候,要传结构体的地址。

总结

本篇文章就到这里了,希望能够给你带来帮助,也希望您能够多多关注我们的更多内容!

(0)

相关推荐

  • C语言结构体指针案例解析

    写结构体指针前,先说一下 . 号和 -> 的区别 记得当初刚学C语言的时候,搞不清结构体的 . 号和 -> ,经常混淆二者的使用. 那么在C语言中 . 号是成员访问运算符,当我们需要访问结构的成员的时候,就会使用到它 而当我们需要使用结构体指针来访问结构成员的时候,就得使用->运算符了. 结构体指针栗子: ​#include<stdio.h> #include<string.h> typedef struct student{ int id; char name[

  • C语言结构体简单入门讲解

    结构体 定义:用于存储不同的数据类型,存储在同一块内存空间里面 关键字 struct 标签 结构体名称 成员 例如: struct student { char name[20]: char sex; int age; float grade; }: 结构体后面不要忘记加分号 结构体至少需要一个标签,证明身份 结构体的使用 .访问指针 →访问 #include <stdio.h> #include <string.h> struct student { char name[20];

  • C语言入门篇--初识结构体

    目录 1.为什么要有结构体 2.结构体的定义 2.1结构体类型的定义 2.2定义结构体普通变量及访问 2.3定义结构体指针变量及访问 1.为什么要有结构体 (1)之前int.char等类型描述的结构体非常单一,只可描述一种类型. (2)数组也是描述同一类型的集合,只可描述一种类型. (3)而结构体使得C语言可以描述复杂类型,比如学生类型( 包含学生的名字.年龄.性别.电话号等信息). 结构体和数组的区别: 结构体:用来描述相同/不同数据元素类型的集合. 数组:用来描述具有相同数据元素类型的集合.

  • C语言中结构体与内存对齐实例解析

    1.结构体类型 C语言中的2种类型:原生类型和自定义类型,结构体类型是一种自定义类型. 2.结构体使用时先定义结构体类型再用类型定义变量 -> 结构体定义时需要先定义结构体类型,然后再用类型来定义变量. -> 也可以在定义结构体类型的同时定义结构体变量. // 定义类型 struct people { char name[20]; int age; }; // 定义类型的同时定义变量. struct student { char name[20]; int age; }s1; // 将类型st

  • C语言结构体计算内存占用问题解析

        c语言中结构体使用是非常广泛的,但是结构体有一个问题,就是如果开头的字段属性是字符类型(char),紧跟着的是其他类型,比如整型.长整型.双精度.浮点型,这时候结构体的大小会发生改变,下面给出一个示例: #include <stdio.h> struct person{ char sex; int age; char name[8]; }; int main() { printf("sizeof(person) = %d\n",sizeof(struct perso

  • C语言结构体的具体使用方法

    目录 初识C语言结构体 1.为什么要有结构体 2.结构体的定义 2.1结构体类型的定义 2.2定义结构体普通变量及访问 2.3定义结构体指针变量及访问 初识C语言结构体 1.为什么要有结构体 (1)之前int.char等类型描述的结构体非常单一,只可描述一种类型. (2)数组也是描述同一类型的集合,只可描述一种类型. (3)而结构体使得C语言可以描述复杂类型,比如学生类型( 包含学生的名字.年龄.性别.电话号等信息). 结构体和数组的区别: ·结构体:用来描述相同/不同数据元素类型的集合. ·数

  • 一篇文章带你用C语言玩转结构体

    目录 前言 一.结构体的声明与定义 1.结构体的声明 2.结构成员的类型 3.结构体的定义 二.初始化结构体 三.访问结构体成员 四.结构体嵌套 五.结构体指针 六.结构体传参 总结 前言 C语言提供了不同的数据类型,比如说int.float.double.char等,不同的类型决定了一个变量在内存中应该占据的空间以及表现形式. 但是,当我们定义一个人的时候,人的不同属性就比较难用同一个数据类型来定义了,因为人的身高.年龄.体重等属性往往需要不同数据类型,在这个时候,我们便引入结构体这个概念.

  • 一篇文章带你了解C语言的选择结构

    目录 一.if-else语句 1.单选择 2.双选择 3.多选择 二.switch语句 总结 一.if-else语句 1.单选择 单选择通过if语句就可以实现,if语句的语法及执行流程如下: if(表达式) { 代码块(表达式返回值为真时执行) } 当程序运行到if语句时,会由表达式进行判定,诺表达式的返回值为真,则进入代码块执行语句,为假便跳过代码块继续执行.(当代码块语句仅有一句时,可以省略大括号.) 举一个简单的例子 例:判断10是否为3的倍数 int main() { int i = 1

  • 一篇文章带你入门C语言:操作符

    目录 操作符 分类 算术操作符 移位操作符 整数存储规则 左右移位规则 赋值操作符 单目操作符 取地址操作符& 解引用操作符* 类型长度操作符sizeof 按位取反操作符~ ++ -- 操作符 强制类型转换操作符(type) 关系操作符= 逻辑操作符 短路运算 条件操作符 逗号表达式 下标引用.函数调用和结构成员 下标引用操作符[] 函数调用操作符() 结构成员操作符. -> 结构体定义 结构体使用 结构体地址 表达式求值 隐式类型转换 整型提升 如何整型提升 有符号数 无符号数 算术转换

  • 一篇文章带你了解C语言:入门基础(2)

    目录 操作符 算术操作符 移位操作符 位操作符 单目操作符 逻辑反操作! 操作符++,-- 逻辑操作符 条件操作符 逗号表达式 常见关键字 typedef extern static 修饰局部变量 修饰全局变量和函数 其它 #define定义常量和宏 定义常量 定义宏 指针 内存单元 指针变量 &取地址操作符,*解引用操作符 类型所占空间 结构体 定义结构体 使用结构体变量 总结 本节将结束对初识C语言的概述,只追求大概,不求精细. 本节包括的内容有操作符,常见关键字,#define定义常量和宏

  • 一篇文章带你了解C语言--数据的储存

    目录 前言 数据类型介绍 类型的基本归类 整形在内存中的存储 原码.反码.补码 大小端介绍 浮点型在内存中的存储 前言 前面我们学习了C语言的一些基本知识和基础的语法,想必大家对C语言都有了自己的认识. 当然只是学习这些知识还是不够的,我们需要进行更加深入的学习. 从本章开始,我们将进行C语言进阶阶段的学习,所以难度会有所增加. 数据类型介绍 前面我们已经学习了基本的内置类型: char //字符数据类型 short //短整型 int //整形 long //长整型 long long //更

  • 一篇文章带你了解C语言操作符

    目录 一.操作符分类 二.算术操作符 三.移位操作符 1.左移操作符 2.右移操作符 2.1算术移位 2.2逻辑移位 四.位操作符 1.按位与 2.按位或 3.按位异或 4.一道练习题 五.赋值操作符 1.赋值操作符(=)是一个很棒的操作符,他可以让你得到一个你之前不满意的值.也就是你可以对其重新赋值. 2.赋值操作符可以连续使用 3.复合赋值符 六.单目操作符 1.逻辑反操作 2.取地址 3.sizeof 4.++和--运算符 4.1前置++和-- 4.2后置++和-- 七.关系操作符 八.逻

  • 一篇文章带你了解C语言的文件操作

    目录 为什么使用文件 什么是文件 程序文件 数据文件 文件名 文件的打开和关闭 文件指针 fopen和fclose函数 文件的顺序读写 总结 为什么使用文件 我们在想既然是通讯录就应该把信息记录下来,只有我们自己选择删除数据的时候,数据才不复存在.这就涉及到了数据持久化的问题,我们一般数据持久化的方法有,把数据存放在磁盘文件.存放到数据库等方式.使用文件我们可以将数据直接存放在电脑的硬盘上,做到了数据的持久化. 什么是文件 磁盘上的文件是文件.但是在程序设计中,我们一般谈的文件有两种:程序文件.

  • 一篇文章带你了解C语言浮点数之间的比较规则

    目录 你认为这段代码输出什么? 为什么不等于呢? 应该怎么解决? 那么怎么判断两个浮点数 f1 和 f2 相等呢. 伪代码 可以简化为 >> 怎么判断浮点数等于0? 还有一个问题 总结 你认为这段代码输出什么? int main() { float f1 = 1.1; float f2 = 2.2; if (f2 - 1.1 == f1) printf("等于"); else printf("不等于"); return 0; } 答案是不等于. 为什么不

  • 一篇文章带你入门C语言:函数

    目录 函数 定义 库函数 定义 介绍 Example 1 strcpy Example 2 memset 自定义函数 Example 1 Example 2 两数交换 链式访问 Example 1 函数声明 函数递归 Example 1 Example 2 函数迭代 Example 3 Example 4 总结 函数 定义 程序里的函数又被叫做子程序,他作为一个大型程序的部分代码,有一或多个语句项组成.函数负责完成某项特定任务,提供了对过程的封装和对细节的隐藏,这样的代码通常会被集成为软件库.

  • 一篇文章带你入门C语言数据结构:绪论

    目录 绪论 什么是数据结构? Example 1 讨论 Example 2 Example 3 Example 4 总结 绪论 什么是数据结构? 不同于计算机操作培训,注意与程序设计的区别. Example 1 求n个数的最大值.次最大值. //1.遍历 - 最朴素的方法 int main() { int arr[10] = { 22,334,552,1,4,6,78,23,55,98 }; int i = 0; int temp = 0; int max1 = arr[0]; int max2

随机推荐