C语言基础7:结构体类型、声明、成员类型、定义、初始化、成员访问、传参

C语言基础7:结构体类型、声明、成员类型、定义、初始化、成员访问、传参

1. 结构体类型的声明

1.1 结构体的基础知识

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

  就好比一个学生,有身高、体重、学号、性别、身份证编号等信息,学生就可以理解为(身高、体重、学号、性别、身份证编号)的集合,而(身高、体重、学号、性别、身份证编号)这些值可称为成员变量,这些成员变量的类型都不一样,有整数、浮点型等

1.2 结构体的声明

//struct:结构体关键字,tag:结构体标签,struct tag:结构体类型
struct tag 
{
 member-list;//成员列表
}variable-list;//变量列表

例如:描述一个学生:

struct Stu
{
 char name[20];//名字
 int age;//年龄
 char sex[5];//性别
 char id[20];//学号
}s1,s2,s3;//分号不能丢,s1,s2,s3是3个全局的结构体变量

int main()
{
 struct Stu s;//局部变量
 return 0;
}
//struct Stu 另一种定义方式
typedef struct Stu
{
 char name[20];//名字
 int age;//年龄
 char sex[5];//性别
 char id[20];//学号
}Stu;//分号不能丢,这里的Stu是类型

int main()
{
 struct Stu student1;//局部变量
 Stu student2;
 return 0;
}

1.3 结构体成员的类型

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

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

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

//初始化:定义变量的同时赋初值。
struct Point p3 = {x, y};
typedef struct Stu        //类型声明
{
 char name[15];//名字
 int age;      //年龄
};
struct Stu s1 = {"zhangsan", 20};//初始化
Stu s2 = {"张三", 21};//初始化
struct Node
{
 int data;
 struct Point p;
 struct Node* next; 
}n1 = {10, {4,5}, NULL}; //结构体嵌套初始化

struct Node n2 = {20, {5, 6}, NULL};//结构体嵌套初始化

struct S s;
strcpy(s.name, "zhangsan");//使用.访问name成员
s.age = 20;//使用.访问age成员
struct Stu
{
 char name[20];
 int age;
};

2. 结构体成员访问

在这里插入图片描述

#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
struct S
{
    int a;
    char c;
    char arr[20];
    double d;
};

struct T
{
    char ch[10];
    struct S s;
    char* pc;
};

int main()
{
    char arr[] = "hello !\n";
    struct T t = { "hehe",{1,'a',"hello world",3.1415926},arr };
    printf("%s\n", t.ch);
    printf("%s\n", t.s.arr);
    printf("%lf\n", t.s.d);
    printf("%s\n", t.pc);
    return 0;
}

  通过函数打印结构体数据:
  方式一:
在这里插入图片描述

#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
typedef struct Stu
{
	char name[20];
	short age;
	char telephone[12];
	char sex[5];
};

void Print1(Stu tmp)
{
	printf("name: %s\n", tmp.name);
	printf("name: %d\n", tmp.age);
	printf("name: %s\n", tmp.telephone);
	printf("name: %s\n", tmp.sex);
}

int main()
{
	Stu s = { "张三", 21,"18866669999", "男" };
	Print1(s);
}

  方式二:
在这里插入图片描述

#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
typedef struct Stu
{
	char name[20];
	short age;
	char telephone[12];
	char sex[5];
};

void Print2(struct Stu* tmp)
{
	printf("name: %s\n", tmp->name);
	printf("name: %d\n", tmp->age);
	printf("name: %s\n", tmp->telephone);
	printf("name: %s\n", tmp->sex);
}

int main()
{
	Stu s = { "张三", 21,"18866669999", "男" };
	Print2(&s);
}

  上面两种方式较好的是第2种,原因:
  对于第①种方式:当Stu s = { "张三", 21,"18866669999", "男" };结构体创建时,假设会占用200个字节的空间。那么此时就占用了200个字节的空间,当函数在传参的时候,又会给 tmp 又会划出200个字节的空间,这样空间浪费就非常严重,同时,数据拷贝也非常消耗时间。
  对于第②种方式:在传参的时候,传的是一个地址过去,也就是占用4或8个字节。之后通过指针找回相关数据,然后进行相关数据的打印。

  总结:函数传参的时候,参数是需要压栈的。如果传递一个结构体对象的时候,结构体过大,参数压栈的的系统开销比较大,所以会导致性能的下降。

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

4. 结构体传参

压栈:

#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
int Add(int x, int y)
{
	int z = 0;
	z = x + y;
	return z;
}

int main()
{
	int a = 10;
	int b = 20;
	int ret = 0;
	ret = Add(a, b);
	return 0;
}

  上面这个函数在我们内存空间是如何完成的呢,首先我们知道,任何一次函数调用,都会在内存当中的栈区上分配一块空间:
(1)栈区:①局部变量②函数的形式参数③函数调用也开辟内存空间
(2)堆区:①动态内存分配,涉及函数:malloc、free、realloc、calloc
(3)静态区:①全局变量②静态变量

  上面函数运行的流程:
(1)进入main函数,此时内存中的栈区会给main函数开辟一块内存单元
(2)之后创建变量:a、b、ret,同时会在分配给main函数的内存单元中再开辟3块儿内存单元区域,分别给a、b、ret。
(3)接下来调用Add函数,当调用Add函数的时候,首先需要进行传参,需要将 a 和 b 这两个参数传过去一个赋给x,一个赋给y,接下来就进行传参:
①先将b进行传参,同时在分配给main函数的内存单元外的栈区分配一块儿空间,这块儿空间叫 y
②a同理,再将a进行传参,再划一块儿内存空间给a,这块儿空间叫 x
(4)接下来进入Add函数,同样的,需要在栈区分配一块儿空间给Add函数,
(5)创建变量 z ,同样是在 Add函数中的内存空间内进行开辟。
(6)将x和y进行相加运算,赋值给z。
这个过程把 a 和 b 放进去了,这个动作叫做压栈操作,

  • 1
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值