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函数。 原因:

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

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

总结

本文介绍的是C语言结构体的一些基础知识,结构体的内容还远远不止这些,在以后学习到了更深的内容之后,或许会再写一篇博客深入介绍。此外,本文参考了小甲鱼的《零基础入门学习C语言》一书,以及网上的部分资料,与自己在学习听课时的笔记,梳理而成。其中或有遗漏之处,或内容的来源,或讲解的疏漏,还请看到的大家多多包含与见谅!

希望能对看到的大家有所帮助!

到此这篇关于C语言结构体的全方面解读的文章就介绍到这了,更多相关C语言 结构体内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

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

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

  • C语言热门考点结构体与内存对齐详解

    目录 一.引例 1.结构体的第一个成员永远放在结构体起始位置偏移量为0的位置 2.从第二个成员开始,总是放在偏移量为一个对齐数的整数处,对齐数=编译器默认的对齐数和变量自身大小的较小值 3.结构体的总大小必须是各个成员的对齐数中最大的那个对齐数的整数倍 二.小试牛刀 三.嵌套结构体的特殊情况 四.关于为什么存在内存对齐 1.平台原因(移植原因): 2.性能原因: 总结 一.引例 到底什么是结构体内存对齐,我们用一段代码来介绍一下 struct S1 { char c1;//1字节 int a;/

  • C语言循环结构详解

    目录 break语句 continue语句 C语言循环结构 一.goto 语句(现在一般很少用) 1.语句介绍: 2.语法结构: 3.goto 语句程序示例: 二.do-while语句 1.语句介绍: 2.语法结构: 3.do-while 流程图: 4.do-while 语句程序示例: 三.while 语句 1.语句介绍: 2.语法结构: 3.while 循环流程图: 4.while 语句程序示例: 四.for 循环语句: 1.语句介绍: 2.语法结构: 3.for 循环语句流程图 4.for

  • C语言之结构体(struct)详解

    目录 为什么需要引入结构体 struct 定义 typedef与#define 结构体变量初始化及成员访问 结构体访问 总结 为什么需要引入结构体 原有的数据类型不能满足需求,因此才设计了构造类型结构体 struct 定义 struct name { 基础类型 结构成员 } 1.无名构造类型 2.有名构造类型 struct student { char name[30]; char sex; int age; float high; }stu; struct student stu2; 3.别名

  • C语言数据结构时间复杂度及空间复杂度简要分析

    目录 一.时间复杂度和空间复杂度是什么? 1.1算法效率定义 1.2时间复杂度概念 1.3空间复杂度概念 二.如何计算常见算法的时间复杂度和空间复杂度 2.1时间复杂度计算 2.2空间复杂度计算 2.3快速推倒大O渐进表达法 三.一些特殊的情况 总结 一.时间复杂度和空间复杂度是什么? 1.1算法效率定义 算法效率分为两种,一种是时间效率--时间复杂度,另一种是空间效率--空间复杂度 1.2时间复杂度概念 时间复杂度,简言之就是你写一个代码,它解决一个问题上需要走多少步骤,需要花费多长时间.打个

  • 浅谈C语言结构体

    目录 前言 什么是结构体 结构体类型的声明 结构的自引用 结构体变量的定义和初始化 结构体的使用 结构体内存对齐 结构体传参 总结 前言 在C语言中,除了内置的许多数据类型,C语言还为我们提供了自定义的数据类型,其中就包括结构体这一数据类型. 今天就让我们来学习一下与结构体相关的知识吧! 什么是结构体 首先我们要知道,什么是结构体? 在现实生活中,每一个事物都是复杂的,拥有许多的属性,为了表示这些属性,我们不可能用单一的数据类型来表示. 例如:一只猫具有的属性有:年龄.体重.名字.品种等等. 为

  • C语言结构体的全方面解读

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

  • C语言结构体的一些理解

    前言 最忙碌的一周已然结束,疲惫之余想和大家聊一聊对C语言中结构体的认识.水平不足,如有问题请大家指正. 一.对结构体的理解 我们知道C语言中有基本数据类型: 1.整(数)型: int:基本整型,用于存储整数,占4个字节,默认值为0 short:短整型,占2个字节 long:长整型,占4个字节 long long:双长整型,占8个字节,比较少用 2.浮点型 float:单精度浮点型,占4个字节 double:双精度浮点型,占8个字节 3.字符型 char:字符型,用于存储单字符,占1个字节. (

  • 一文读懂c语言结构体在单片机中的应用

    Struck 看到单片机中有很多struck 的应用,但是呢我当初学C语言的时候又没有很认真的去学习,今天复习下,写一篇小小的交流,希望能够给大家带来帮助. 1.struck的定义 /***********方式一**********/ struct Book { char title[128]; char aurhor[40]; float price; unsigned int date; char pubilsher[40]; }; /*定义了Book这个模板*/ struct Book b

  • 详解C语言结构体,枚举,联合体的使用

    目录 一.匿名结构体 二.结构体的自引用 1.声明时不要自己引用自己 2.结构体重命名时不能使用重命名 三.结构体内存对齐规则 1.结构体内存计算 2.结构体嵌套 3.通过调整结构体成员顺序,压缩内存 四.存在内存对齐的原因 五.修改默认对齐数 六.结构体传参 七.位段 1.位段在内存中的存储 2.位段的跨平台问题 八.枚举 1.枚举的定义 2.枚举的优点 九.联合体(共用体) 1.联合体大小的计算 2.使用联合体判断计算机的大小端字节序 一.匿名结构体 struct { char name[2

  • php读取二进制流(C语言结构体struct数据文件)的深入解析

    尽管php是用C语言开发的,不过令我不解的是php没有提供对结构体struct的直接支持.不过php提供了pack和unpack函数,用来进行二进制数据(binary data)和php内部数据的互转: 复制代码 代码如下: string pack ( string $format [, mixed $args [, mixed $...]] )   //Pack given arguments into binary string according to format.  array unp

  • C语言 结构体(Struct)详解及示例代码

    前面的教程中我们讲解了数组(Array),它是一组具有相同类型的数据的集合.但在实际的编程过程中,我们往往还需要一组类型不同的数据,例如对于学生信息登记表,姓名为字符串,学号为整数,年龄为整数,所在的学习小组为字符,成绩为小数,因为数据类型不同,显然不能用一个数组来存放. 在C语言中,可以使用结构体(Struct)来存放一组不同类型的数据.结构体的定义形式为: struct 结构体名{     结构体所包含的变量或数组 }; 结构体是一种集合,它里面包含了多个变量或数组,它们的类型可以相同,也可

  • C语言结构体(struct)常见使用方法(细节问题)

    基本定义:结构体,通俗讲就像是打包封装,把一些有共同特征(比如同属于某一类事物的属性,往往是某种业务相关属性的聚合)的变量封装在内部,通过一定方法访问修改内部变量. 结构体定义: 第一种:只有结构体定义 struct stuff{ char job[20]; int age; float height; }; 第二种:附加该结构体类型的"结构体变量"的初始化的结构体定义 //直接带变量名Huqinwei struct stuff{ char job[20]; int age; floa

  • Go语言结构体定义和使用方法

    本文实例讲述了Go语言结构体定义和使用方法.分享给大家供大家参考.具体分析如下: 一个结构体(struct)就是一个字段的集合. (而 type 定义跟其字面意思相符.) 复制代码 代码如下: package main import "fmt" type Vertex struct {     X int     Y int } func main() {     fmt.Println(Vertex{1, 2}) } 结构体字段使用点号来访问. 复制代码 代码如下: package

  • C语言 结构体数组详解及示例代码

    所谓结构体数组,是指数组中的每个元素都是一个结构体.在实际应用中,结构体数组常被用来表示一个拥有相同数据结构的群体,比如一个班的学生.一个车间的职工等. 定义结构体数组和定义结构体变量的方式类似,请看下面的例子: struct stu{ char *name; //姓名 int num; //学号 int age; //年龄 char group; //所在小组 float score; //成绩 }class[5]; 表示一个班级有5个学生. 结构体数组在定义的同时也可以初始化,例如: str

  • C语言结构体定义的方法汇总

    什么是结构体? 在C语言中,结构体(struct)指的是一种数据结构,是C语言中聚合数据类型(aggregate data type)的一类.结构体可以被声明为变量.指针或数组等,用以实现较复杂的数据结构.结构体同时也是一些元素的集合,这些元素称为结构体的成员(member),且这些成员可以为不同的类型,成员一般用名字访问. 结构体与数组的比较 (1) 都由多个元素组成 (2) 各个元素在内存中的存储空间是连续的 (3) 数组中各个元素的数据类型相同,而结构体中的各个元素的数据类型可以不相同 结

随机推荐