自定义类型(1):结构体

1. 结构体声明和结构体类型定义

同一种类型的数据的集合是数组,和数组不同,结构体是多种类型的数据的集合。

假设我们要存储一个学生的信息,里面包含了名字、性别、年龄等等信息,就需要用到结构体。

1.1 结构体的声明规则

//声明一个结构体stu,stu是结构体名
//结构体里的声明是结构体成员
struct stu
{   
   char name[20];//名字
   int age;//年龄
   char sex[5];//性别
   char id[20];//学号
};//必须要有分号

该声明描述了一个由三个字符数组和一个int型变量组成的结构。该声明并未创建实际的数据对象,只描述了该对象由什么组成。

1.2 结构体类型的定义

  • 定义结构体类型变量

上述只是结构体的声明,要想真正存储数据还需要定义实体变量

struct stu data;//定义一个struct stu型的结构体变量data

编译器执行这行代码便创建了一个结构变量data。编译器使用stu模板为该变量分配空间(如下图所示)
在这里插入图片描述

  • 还可以定义多个struct std类型的变量,包括指针变量
struct std means,document,*ptstd;//定义结构体变量

结构体变量means和document中都包括name、sex、age、id部分。指针ptstd可以指向任意struct std类型的结构体变量,例如means,document。

  • 结构体局部变量与结构体全局变量
struct stu
{   
  //……中间代码省略
}a2;//定义一个全局变量a2,类型为struct stu
int main()
{
   struct stu a1;//定义一个局部变量a1,类型为struct stu
   return 0;
}

1.3 匿名结构体

//声明一个匿名结构体
struct
{
   int a;
};
  • 提问:如果创建两个匿名结构体,编译器能否分清楚谁是谁?
struct
{
	int a;
}*p;
struct
{
	int a;
}b1;
int main()
{
	p = &b1;
	return 0;
}

答案必然的,并且编译器会把上面的两个声明当成完全不同的两个类型,所以上述代码是非法的。

2. 访问结构体元素的方式

2.1 初始化结构体类型

  • 初始化结构体变量也可以像普通变量和数组那样,以std为例:
struct std data = { "zhangsan",12,"man",123 };

这种初始化的方式,要一一对应结构体成员的类型,用逗号分隔。

2.2 用“.”运算符(句点运算符)访问

  • 除了直接初始化,还可使用句点运算符来访问结构体元素,达到初始化的效果
struct A
{
	int a;
};

int main()
{
	struct A a1;//定义
	a1.a = 1; //初始化
	printf("%d\n", a1.a);
	return 0;
}

2.3 用指针访问

  • 要用指针访问结构A,首先要拿到struct A类型的成员的地址,然后进到该对象的内存空间进行访问

下面的代码就是拿到了结构体变量a1的地址,a1为struct A类型,那么它的地址就为struct A*类型,对应p1的类型,就可以赋值给p1。

拿到了它的地址以后就可以通过:
(1)箭头运算符解引用访问到它的成员a,并且给a赋值初始化;
(2)指针+句点运算符访问:p1指针变量存放a1的地址,解引用就是a1,那么就可以用句点运算符访问。(注意优先级,要先解引用p1再用句点运算符)

struct A
{
	int a;
};

int main()
{
	struct A a1;
	struct A* p1 = &a1;
	p1->a = 1;
	printf("%d\n", p1->a);
	(*p1).a = 2;
	printf("%d\n", (*p1).a);
	return 0;
}

3. 结构体传参

struct S
{
  int data[1000];
  int num;
};
  struct S s = {{1,2,3,4}, 1000};
//结构体传参
void print1(struct S s)
{
  printf("%d\n", s.num);
}
//结构体地址传参
void print2(struct S* ps)
{
  printf("%d\n", ps->num);
}
int main()
{
  print1(s);  //传结构体
  print2(&s); //传地址
return 0;
}

上面的 print1 和 print2 函数哪个好些?

答案是:首选print2函数。

  • 原因
    函数传参的时候,参数是需要压栈的。 如果传递一个结构体对象的时候,结构体过大,参数压栈
    的系统开销比较大,所以会导致性能的下降。
  • 结论
    结构体传参的时候,要传结构体的地址。
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

久菜

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值