初阶结构体(超详解)

初阶结构体

    • [1. 结构体的声明](#1. 结构体的声明)
      • [1.1 结构的基础知识](#1.1 结构的基础知识)
      • [1.2 结构的声明](#1.2 结构的声明)
      • [1.3 结构成员的类型](#1.3 结构成员的类型)
      • [1.4 结构体变量的初始化和定义](#1.4 结构体变量的初始化和定义)
    • [2. 结构体的访问](#2. 结构体的访问)
    • [3. 结构体传参](#3. 结构体传参)

1. 结构体的声明

1.1 结构的基础知识

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

结构- ->(结构体)

对比:

1.2 结构的声明

c 复制代码
struct Stu
{
	//学生相关属性
	char name[20];
	int age;
	char sex[5];
	char id[20];
}s3,s4;//不可省略;
//s3,s4是结构体变量类型
//s3,s4是全局的
int main()
{
	struct Stu s1;
	struct Stu s2;
	//s1,s2是结构体类型的变量,是局部的
	struct Stu s3;
	return 0;
}

该类型定义不可缺少struct

让我们看看下面这种定义方式:(可省略struct)

c 复制代码
typedef struct Stu
{
	//学生相关属性
	char name[20];
	int age;
	char sex[5];
	char id[20];
}Stu;//Stu是重新定义的新类型
int main()
{
	struct Stu s1;
	struct Stu s2;
	//s1,s2是结构体类型的变量,是局部的
	Stu s5;//typedef定义下可省略struct
	return 0;
}

1.3 结构成员的类型

结构体变量的成员可以是标量,数组,指针,甚至是其他结构体

c 复制代码
struct B
{
	char c;
	int i;
};

struct S
{
	char c;
	int num;
	int arr[10];
	double* pd;
	struct B sb;
	struct B* pb;
};
int main()
{
	return 0;
}

1.4 结构体变量的初始化和定义

有了结构体类型,那如何定义变量,其实很简单。

c 复制代码
struct B
{
	char c;
	int i;
};
struct S
{
	char c;
	int num;
	int arr[10];
	double* pd;
	struct B sb;
	struct B* pb;
}s1;//s1是全局变量
struct S s2;//s2是全局变量
int main()
{
	double d = 3.14;
	//按照顺序初始化
	struct S s3 = { 'q', 100, {1,2,3}, &d, {'a', 99}, NULL };//局部变量
	//指定成员来初始化
	struct S s4 = { .num = 1000, .arr = {1,2,3,4,5} };//局部变量
	return 0;
}

2. 结构体的访问

  • 结构体变量访问成员
    结构变量的成员是通过点操作符(.)访问的。点操作符接受两个操作数。
  • 结构体指针访问指向变量的成员
    有时候我们得到的不是一个结构体变量,而是指向一个结构体的指针。用(->)访问1

案例1:

c 复制代码
#include <string.h>

struct S
{
	char name[20];
	int age;
};
void set_s(struct S t)
{
	t.age = 18;
	//t.name = "zhangsan";//err, 因为name是数组名,数组名是常量的地址
	strcpy(t.name, "zhangsan");//字符串拷贝
}
int main()
{
	struct S s = { 0 };
	//写一个函数给s中存放数据
	set_s(s);
	return 0;
}

上方代码错误

修改如下:

c 复制代码
//void set_s(struct S* ps)
//{
//	(*ps).age = 18;
//	//t.name = "zhangsan";//err, 因为name是数组名,数组名是常量的地址
//	strcpy((*ps).name, "zhangsan");//字符串拷贝
//}

//
void set_s(struct S* ps)
{
	ps->age = 18;
	//t.name = "zhangsan";//err, 因为name是数组名,数组名是常量的地址
	strcpy(ps->name, "zhangsan");//字符串拷贝
}

void print_s(struct S* ps)
{
	printf("%s %d\n", ps->name, ps->age);
}

int main()
{
	struct S s = {0};
	//写一个函数给s中存放数据
	set_s(&s);

	//写一个函数打印s中的数据
	print_s(&s);

	return 0;
}

3. 结构体传参

直接上代码:

c 复制代码
struct S
{
	char name[20];
	int age;
};
void set_s(struct S* ps)
{
	ps->age = 18;
	//t.name = "zhangsan";//err, 因为name是数组名,数组名是常量的地址
	strcpy(ps->name, "zhangsan");//字符串拷贝
}

void print1(struct S ps)
{
	printf("%s %d\n", ps.name, ps.age);
}
int main()
{
	struct S s = { 0 };
	//写一个函数给s中存放数据
	set_s(&s);

	//写一个函数打印s中的数据
	print1(s);

	return 0;
}
//
//
struct S
{
	char name[20];
	int age;
};
void set_s(struct S* ps)
{
	ps->age = 18;
	//t.name = "zhangsan";//err, 因为name是数组名,数组名是常量的地址
	strcpy(ps->name, "zhangsan");//字符串拷贝
}

void print2(struct S* ps)
{
	printf("%s %d\n", ps->name, ps->age);
}
int main()
{
	struct S s = {0};
	//写一个函数给s中存放数据
	set_s(&s);

	//写一个函数打印s中的数据
	print2(&s);

	return 0;
}

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

结构体对象的时候,结构体过大,参数压栈的的系统开销比较大,所以会导致性能的下降。

结论:

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

不知不觉,结构体初阶以告一段落。通读全文的你肯定收获满满,让我们继续为C语言学习共同奋进

相关推荐
风逸hhh1 小时前
python打卡day29@浙大疏锦行
开发语言·前端·python
浩皓素1 小时前
深入理解For循环及相关关键字原理:以Python和C语言为例
c语言·python
ᖰ・◡・ᖳ2 小时前
JavaScript:PC端特效--缓动动画
开发语言·前端·javascript·css·学习·html5
hy____1232 小时前
C++多态的详细讲解
开发语言·c++
小葡萄20252 小时前
黑马程序员C++2024版笔记 第0章 C++入门
开发语言·c++·笔记
万物此臻2 小时前
C#编写软件添加菜单栏
开发语言·c#
RongSen333 小时前
Python海龟绘图(Turtle Graphics)核心函数和关键要点
开发语言·python
小贾要学习3 小时前
【C语言】贪吃蛇小游戏
c语言·开发语言·游戏
人类恶.3 小时前
C 语言学习笔记(函数2)
c语言·笔记·学习
程序员爱钓鱼3 小时前
defer关键字:延迟调用机制-《Go语言实战指南》
开发语言·后端·golang