【C语言】结构体详解(定义、访问、初始化、自引用和传参)

1、结构体的定义

结构体是一种用户自定义的数据类型,它允许存储不同类型的数据项
结构体由一系列具有相同类型或不同类型的数据成员构成,可以像基本数据类型一样被声明和使用。

其中,结构体名为自定义的标识符,可以是任何合法的标识符;成员可以是基本数据类型(例如 int、float、char 等),也可以是其他结构体类型、指针类型等。

例如,我们可以定义一个表示学生信息的结构体,包括姓名、年龄和分数。

struct Student
{
	char name[20];
	int age;
	double score;
};

我们可以使用这个结构体来定义一个 Student 类型的变量

struct Student stu;// 声明一个名为 stu 的 Student 类型的结构体变量

我们也可以使用 typedef 来定义一个结构体类型的别名(对结构体进行重命名)

typedef struct Student
{
	char name[20];
	int age;
	double score;
} s1;//此时s1就相当于是struct Student

2、结构体的访问

通过结构体变量名和成员名使用“.”操作符进行访问,例如:

struct Student s1;
s1.score = 94;
strcpy(s1.name, "lzy");
s1.age = 20;

通过指向结构体的指针使用“->”操作符进行访问,例如:

struct Student* ps1;
ps1 = &s1;
ps1->score = 94;
strcpy(ps1->name, "lzy");
ps1->age = 20;

两种方法的具体应用

#include <stdio.h>

// 定义结构体类型
struct student 
{
	char name[20];
	int age;
	double score;
};

int main() 
{
	// 定义结构体变量并初始化
	struct student s1 = { "lisi", 18, 94};
	// 定义结构体指针变量并赋值
	struct student* ps = &s1;
	// 使用点操作符访问结构体变量的成员
	printf("%s, %d\n", s1.name, s1.age, s1.score);
	// 使用箭头操作符访问结构体指针变量的成员
	printf("%s, %d\n", ps->name, ps->age, ps->score);
	return 0;
}

3、结构体的自引用

结构体的自引用指的是结构体中包含指向本身类型的指针成员。
这种结构体的定义方式可以让我们在一个结构体中嵌套另一个相同类型的结构体,从而实现对数据的更加复杂的描述。

struct Node 
{
	int data;
	struct Node* next;
};
//通过这种方式,我们就可以使用链表来存储一系列数据了。

错误的自引用方式

struct Node
{
	int data;
	struct Node next;
};

在这段代码中,结构体 Node 的成员 next 的类型是 struct Node(即 Node 结构体本身),这会导致结构体无限递归地包含自身,最终导致无限扩大结构体的大小,从而可能导致程序崩溃。

使用typedef时的错误的自引用方式

typedef struct
{
	int data;
	Node* next;
}Node;

这段代码中的 Node 在定义时是没有被声明的,但在结构体定义时已经使用,且定义时的 Node 是指向自身的指针,这就需要先声明一个 Node 类型的结构体再定义它
修正后

typedef struct Node 
{
	int data;
	struct Node* next;
}Node;

4、结构体的初始化

结构体变量可以在定义的同时进行初始化,或者在定义之后通过赋值或memset()函数进行初始化。

①定义的同时进行初始化(直接赋值)

struct Student s1
{
char name[20];
int age;
double score;
}s1 = { 张三,21,91 };

②逐个赋值

struct Student s2;
s2.age = 19; // 赋值年龄
strcpy(s2.name, "Jack"); // 结构体变量中的字符串类型需要使用strcpy()函数进行赋值
s2.score = 90; // 赋值分数

③使用memset()函数

struct Student s3;
memset(&s3, 0, sizeof(s3)); // 使用memset()函数将整个结构体变量置零

5、结构体传参

结构体传参的有两种方式,分别是通过传递结构体和传递指针的方式传递结构体变量。
例如

struct Student
{
	char name[20];
	int age;
};

struct Student s1 = { "wangwu",25 };

void print1(struct Student s1)
{
	printf("%d\n", s1.name,s1.age);
}

void print2(struct Student* ps1)
{
	printf("%d\n", ps1->name,ps1->age);
}

int main()
{
	print1(s1);  //传递结构体
	print2(&s1); //传递指针
return 0;
}

如果使用传值方式将一个结构体传递给函数,那么这个结构体就需要在内存中复制一份,这样会占用较多的时间和硬件资源。
而使用传指针的方式来传递结构体参数时,只需要传递结构体的地址,这不仅减少了在内存中复制结构体所需的时间和资源,还可以避免由于结构体复制造成的内存泄漏问题。
所以,结构体传参首选传地址的方式。

  • 3
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
C语言之基础 1) C语言之简介 2) C语言之搭建开发环境 3) C语言之第一个简单程序的结构详解 4) C语言之书写规范和注释 5) C语言数据类型 字符串和格式化输入输出 6) C语言之使用字符串 7) C语言之格式化输出 8) C语言之格式化输入 9) C语言之格式化输入输出整理 10) C语言之基本运算符 11) C语言之其他运算符 12) C语言之表达式和语句 循环语句 13) C语言之while循环语句 14) C语言之do-while循环语句 15) C语言之for循环语句 16) C语言之使用关系运算符和表达式 17) C语言之赋值运算+=、-=、*=、/=、%= 18) C语言之循环嵌套 分支跳转 19) C语言之分支和跳转 if 20) C语言之分支和跳转 if-else 21) C语言之条件运算符 ?: 22) C语言之循环辅助手段:continue 和 break 23) C语言之分支和跳转 switch和break 24) C语言之分支和跳转 goto语句 25) C语言之字符输入/输出和输入确认 指针 26) C语言之初识指针 27) C语言之指针的简单用法 28) C语言之字符串指针详解 数组 29) C语言定义数组 30) C语言之一维数组的使用 31) C语言之二维数组和多维数组 32) C语言之指向数组的指针 33) C语言之保护数组内容const的使用 34) C语言之指向多维数组的指针 函数 35) C语言函数定义和调用 36) C语言定义带参数的函数 37) C语言函数之形参和实参 38) C语言函数之返回值和函数类型 39) C语言之指针做函数参数 40) C语言之数组做函数参数 41)c语言之递归 字符串和字符串函数 42)c语言之字符串I/O 43) C语言之字符串输入/输出 44) C语言之字符串处理函数 文件操作 45) C语言之文件是什么 46) C语言之用fopen() 打开文件,关闭文件 fclose() 47) C语言之getc() 和 putc 读写文件 48) C语言之文件结尾 49) C语言之fgets() 和 fputs() 50) C语言之文件内部指针 51) C语言之rewind() 52) C语言之随机存取 fseek() 和 ftell() 函数 53) C语言之fsetpos和fgetpos 54) C语言之fread() 和 fwrite() 函数 结构体和其他数据形式 55) C语言结构体定义初始化 56) C语言访问结构体成员 57) C语言结构数组 58) C语言结构体指针 59) C语言结构体函数参数 60) C语言之把结构体保存到文件 已更新至此 61)C语言之联合简介 62)C语言之枚举类型 63)C语言函数和指针 位操作 64) C语言之二进制、位和字节 65)C语言之位运算 66)C语言之打开位 67) C语言之转置位及查看位 68) C语言之左移右移(大结局)
C语言结构体数组可以在定义的同时进行初始化。例如,可以使用顺序初始化的方式为结构体数组的每个元素赋初值。通过定义一个结构体类型,并在定义数组变量时使用花括号来初始化数组元素。每个花括号内部的值按照结构体成员的顺序对应赋值给数组元素的成员。 另外,还可以使用memset函数和bzero函数结构体数组进行初始化。这两个函数都可以将指定内存区域的值设置为指定的值或者0。其,memset函数需要提供三个参数,分别是指向要初始化的内存区域的指针、要设置的值以及要初始化的内存区域的大小。而bzero函数只需要提供两个参数,其第一个参数是要初始化的内存区域的指针,第二个参数是要初始化的内存区域的大小,初始化的值默认为0。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [C语言 结构体数组详解及示例代码](https://download.csdn.net/download/weixin_38679233/13999358)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 33.333333333333336%"] - *2* [C语言结构体初始化的几种方法](https://blog.csdn.net/u010835747/article/details/117459812)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 33.333333333333336%"] - *3* [关于数组结构体初始化](https://blog.csdn.net/BlueLoveyyt/article/details/45958125)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 33.333333333333336%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值