初始结构体

本文详细介绍了C++和C中结构体的基础知识,包括结构体的声明、成员访问及传参。讨论了结构体变量的定义与初始化,强调了结构体成员可以是不同类型的变量,包括标量、数组、指针等。同时,对比了结构体变量和指针访问成员的区别,并分析了值传递与引用传递在结构体传参时的性能差异,提倡使用传址方式以提高效率。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


1. 结构体的声明

1.1 结构的基础知识

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

(数组是一组相同类型元素的集合)

生活中的对象大多是复杂的,有多种属性,结构体就是用来描述复杂对象的。

1.2 结构的声明

结构体的语法形式:

struct tag//分别是结构体关键字、结构体标签(名字可变)
{
      member-list;//成员列表,可以放多个成员,成员之间可以是不同类型
}variable-list;//变量列表

例如声明一个学生的结构体类型:

一种结构体变量的创建(定义)方式


struct Stu
{
	char name[20];//名字
	int age;//年龄
	char sex[5];//性别
	char id[20];//学号
	float score;//学分
};//分号不能丢
	
int a = 0;//拿整型这种类型创建了a变量
int b = 0;//拿整型这种类型创建了b变量

//即可以拿类型创建变量
//则现在有了一个结构体类型——学生类型,拿这个类型怎么创建变量呢?
	
//struct Stu就是结构体类型,如创建一个s变量:
	
struct Stu s;//定义了一个结构体变量s,是局部变量

//即这里用了struct Stu这种结构体类型创建了(定义)一个结构体变量s

另一种结构体变量的创建(定义)方式

struct Stu
{
	char name[20];//名字
	int age;//年龄
	char sex[5];//性别
	char id[20];//学号
	float score;//学分
}s1, s2;

//s1和s2是拿这个结构体类型创建的两个结构体变量
//还可以继续创建很多个变量,所以是变量列表。

这里的s1、s2和上面s的创建的效果一模一样;
但是差异是:
这里的s1、s2是全局变量,上面的s是局部变量。

全局变量不初始化默认是0。

1.3 结构成员的类型

结构的成员可以是标量(像int a)、数组、指针,甚至是其他结构体。

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

有了结构体类型(如struct Stu),那如何定义结构体变量呢?

结构体成员的初始化:

#include <stdio.h>
struct Stu
{
	char name[20];
	int age;
	char sex[5];
	char id[20];
	float score;
};
int main()
{
	struct Stu s = { "zhangsan",20,"男","19",95.5f };
	printf("%s %d %s %s %.1f\n", s.name, s.age, s.sex, s.id, s.score);
	return 0;
}//zhangsan 20 男 19 95.5

结构体里再包含一个结构体的定义和初始化、访问:

#include <stdio.h>
struct S
{
	int a;
	char c;
	double d;
};
struct Stu
{
	struct S ss;//这里结构体里包含一个结构体
	char name[20];
	int age;
	char sex[5];
	char id[20];
	float score;
};
int main()
{
	struct Stu s = { {100,'w',3.14},"zhangsan",20,"男","19",95.5f};
//这里把{100,'w',3.14}这些数据给了ss,即给了ss初始化
	printf("%d %c %.2lf %s %d %s %s %.1f\n",s.ss.a,s.ss.c,s.ss.d,s.name, s.age, s.sex, s.id, s.score);
	return 0;
}//100 w 3.14 zhangsan 20 男 19 95.5

结构体里包含一个结构体访问:结构体里包含一个结构体成员,结构体成员里又找自己的结构成员,用了两层.(两层点)。

注意:

95.5f表明是float类型的值,不写f则编译器会默认这是double类型的值。
打印的时候,f%表明打印的是float类型的数据;lf%表明是double类型的

struct Point
{
int x;
int y;
}p1; //声明类型的同时定义变量p1
struct Point p2; //定义结构体变量p2

//初始化:定义变量的同时赋初值

2. 结构体成员的访问

1、结构体变量访问成员

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


可以看到 s 有成员 name 和 age ;
那如何访问s的成员?

#include <stdio.h>
struct Stu
{
	char name[20];
	int age;
};
int main()
{
	struct Stu s = { "lisi",18 };
	printf("%s %d\n", s.name, s.age);
	return 0;
}//lisi 18

2、结构体指针访问指向变量的成员

有时候我们得到的不是一个结构体变量,而是指向一个结构体的指针,则用—>操作符
那该如何访问成员。
如下:

#include <stdio.h>
struct Stu
{
	char name[20];
	int age;
};
void Print(struct Stu* ps)
{
	printf("name=%s age=%d\n", (*ps).name, (*ps).age);
	//使用结构体指针访问指向对象的成员
	printf("name=%s age=%d\n", ps->name, ps->age);
}
int main()
{
	struct Stu s = { "zhangsan",20 };
	Print(&s);//结构体地址传参
	return 0;
}//打印结果:
//name=zhangsan age=20
//name=zhangsan age = 20

3. 结构体传参

写Print1函数传参:

#include <stdio.h>
struct S
{
	int arr[1000];
	float f;
	char ch[100];
};
void Print1(struct S tmp)
{
	int i = 0;
	for (i = 0; i < 10; i++)
	{
		printf("%d ", tmp.arr[i]);
	}
	printf("\n");
	printf("%.1f\n", tmp.f);
	printf("%s\n", tmp.ch);
}
int main()
{
	struct S s = { {1,2,3,4,5,6,7,8,9,10},5.5f,"hello world"};
	Print1(s);
	return 0;
}//输出:
//1 2 3 4 5 6 7 8 9 10
//5.5
//hello world

此代码是值传递,函数调用时是传值调用
当s传给tmp时,传值调用时会再创建一个临时空间,实参传给形参时形参其实是实参的一份临时拷贝,即肯定会拷贝一份空间,本来s(结构体)的空间就很大了,再临时创建一个一样的,大大造成了空间的浪费,数据拷贝也需要时间,系统开销很大。

则重新设计一个函数Print2:

#include <stdio.h>
struct S
{
	int arr[1000];
	float f;
	char ch[100];
};
void Print2(struct S* ps)
{
	int i = 0;
	for (i = 0; i < 10; i++)
	{
		printf("%d ", ps->arr[i]);//ps指向对象s中的成员arr数组
	}
	printf("\n");
	printf("%.1f\n", ps->f);//ps指向对象s的成员f;结构体指针->f,因为ps是结构体指针,它里面存的是s的地址所以它指向了找到s的成员f
	printf("%s\n", ps->ch);
}
int main()
{
	struct S s = { {1,2,3,4,5,6,7,8,9,10},5.5f,"hello world" };
	Print2(&s);
	return 0;
}//输出:
//1 2 3 4 5 6 7 8 9 10
//5.5
//hello world

上面的 print1 和 print2 函数哪个好些?
答案是:首选print2函数。
原因:函数传参的时候,参数是需要压栈的。
如果传递一个结构体对象的时候,结构体过大,参数压栈的的系统开销比较大,所以会导致性能的下降。
结论:结构体传参的时候,要传结构体的地址

函数调用传参的过程:(怎么传参的呢?)

任何函数的调用都要在内存中开辟空间。内存中分为栈区、堆区和静态区这3个区域。任何函数的每一次函数的调用都要在内存中的栈区申请空间。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值