初阶结构体(超详解)

初阶结构体

    • [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语言学习共同奋进

相关推荐
一颗花生米。13 分钟前
深入理解JavaScript 的原型继承
java·开发语言·javascript·原型模式
问道飞鱼14 分钟前
Java基础-单例模式的实现
java·开发语言·单例模式
学习使我快乐0117 分钟前
JS进阶 3——深入面向对象、原型
开发语言·前端·javascript
通信仿真实验室1 小时前
(10)MATLAB莱斯(Rician)衰落信道仿真1
开发语言·matlab
勿语&1 小时前
Element-UI Plus 暗黑主题切换及自定义主题色
开发语言·javascript·ui
代码雕刻家4 小时前
数据结构-3.9.栈在递归中的应用
c语言·数据结构·算法
吾爱星辰5 小时前
Kotlin 处理字符串和正则表达式(二十一)
java·开发语言·jvm·正则表达式·kotlin
ChinaDragonDreamer5 小时前
Kotlin:2.0.20 的新特性
android·开发语言·kotlin
IT良5 小时前
c#增删改查 (数据操作的基础)
开发语言·c#
Kalika0-06 小时前
猴子吃桃-C语言
c语言·开发语言·数据结构·算法