程序员Feri一名12年+的程序员,做过开发带过团队创过业,擅长Java、鸿蒙、嵌入式、人工智能等开发,专注于程序员成长的那点儿事,希望在成长的路上有你相伴!君志所向,一往无前!
1.结构体指针
结构体指针:指向结构体变量的指针 (将结构体变量的起始地址存放在指针变量中)
具体应用场景:
-
可以指向单一的结构体变量
-
可以用作函数的参数
-
可以指向结构体数组
定义结构体指针变量格式:
struct 结构体名 *结构体指针变量名;
示例:
struct Person {
char name[50];
char sex[10];
int age;
};
struct Person *person1;
说明:变量 person1 是一个指针,指向的数据是 struct Person 类型的实例。
2.结构体传参
如果将 struct 变量传入函数,函数内部得到的是一个原始值的副本。
#include <stdio.h>
struct Person {
char *name;
int age;
char *address;
};
void addAge(struct Person per) {
per.age = per.age + 1;
}
int main() {
struct Person p1 = {"Tom", 20, "北京市海淀区"};
addAge(p1);
printf("age = %d\n", p1.age); // 输出 20
return 0;
}
函数 addAge() 要求传入一个 struct 变量 per,但实际上传递的是 struct 变量p1的副本
,改变副本影响不到函数外部的原始数据。
通常情况下,开发者希望传入函数的是同一份数据,函数内部修改数据以后,会反映在函数外部。而且,传入的是同一份数据,也有利于提高程序性能。这时就需要将 struct 变量的指针传入函数,通过指针来修改 struct 属性。
3. -> 操作符
C 语言就引入了一个新的箭头运算符( ->
),可以从结构体指针上直接获取属性,大大增强了代码的可读性。
void addAge(struct Person * per) {
per->age = per->age + 1; //使用结构体指针访问指向对象的成员
}
总结:如果指针变量p指向一个结构体变量stu,以下3种用法等价:
① stu.成员名 stu.num
② (*p).成员名 (*p).num
③ p->成员名 p->num
4. 数据结构中使用结构体
4.1 声明结点的结构体
链表是一种动态的数据存储结构(非固定长度),链表的基本单位是结点(node)
,同一链表的所有结点具有相同的数据类型。而结点使用结构体
类型进行定义。
一个链表结点包括数据域和指针域两部分:数据域存储需要处理的数据、指针域存储下一个结点的位置。
单链表结构的结点定义如下:
struct Node {
int data; //这里默认的是int型,如需其他类型可修改
struct Node *next; //指向Node型变量的指针
};
二叉树结构的结点定义如下:
struct BTNode {
int data; //这里默认的是int型,如需其他类型可修改
struct BTNode *lchild; //指向左孩子结点指针
struct BTNode *rchild; //指向右孩子结点指针
};
4.2 声明结点变量
不需要事先说明链表所包括的结点个数,新数据到达时创建结点变量即可
以创建二叉树结点为例:
BTNode *bt;
bt = (BTNode*) malloc(sizeof (BTNode));//此句要熟练掌握
执行过程为:先定义一个结点的指针bt,然后用函数malloc()来动态申请
一个结点的内存空间,接着让指针 bt 指向这片内存空间,这样就完成了一个结点变量的创建。后续不需要数据时,删除结点,释放空间(使用free(bt)
释放)即可。
5. malloc()模板
模板:(当需要制作一个新结点时,只要把结点结构型的名称填入括号中的“类型”处即可)
类型 *p;
p = (类型 *)malloc(sizeof(类型)); //将=右边创建的结点的地址赋给p
示例:
typedef struct BTNode {
int data;
struct BTNode *lchild;
struct BTNode *rchild;
}BTNode;
int main() {
BTNode *newNode;
newNode = (BTNode *) malloc(sizeof(BTNode));
return 0;
}
好了,本篇就到这里啦,学习这件事,就是需要坚持,没有其他的技巧,加油,小伙儿伴们!