C 语言 struct 第一个成员变量的妙用
2024-09-06 22:50:20
一、双重身份
如下定义了一个 School 结构体:
typedef struct School
{
int a;
int b;
}SCHOOL_S;
SCHOOL_S stSch;
下面我们来输出一下 stSch 以及成员变量 a 和 b 的地址:
int main()
{
printf("stSch 的地址[%p]\n", &stSch);
printf(" a 的地址[%p]\n", &stSch.a);
printf(" b 的地址[%p]\n", &stSch.b);
return 0;
}
输出结果如下:
有没有发现什么不得了的事情——结构体 school 的地址与第一个成员变量 a 的地址相同,也就是说变量 a 的地址既是 school * 类型,又是 int * 类型。脑海中突然冒出一个大胆的想法,如果我将 a 的地址强制类型转化为 SCHOOL_S * 类型呢:
int main()
{
stSch.a = 10;
stSch.b = 20;
SCHOOL_S *pstSch = (SCHOOL_S *)&stSch.a;
printf("a = %d\n", pstSch->a);
printf("b = %d\n", pstSch->b);
return 0;
}
输出结果如下:
Amazing~
二、妙用
通过上边的小测试,我们发现了 struct 的第一个成员变量的地址有双重身份,那么该如何使用呢?
对于两个不同的结构体:
typedef struct Teacher
{
char name[10]; /* 姓名 */
int id; /* 职工编号 */
}TEACHER_S;
typedef struct School
{
char name[10]; /* 校名 */
int cnt; /* 教职工个数 */
}SCHOOL_S;
SCHOOL_S school;
TEACHER_S teacher;
void Init()
{
strncpy(stSchool.name, "School", sizeof(stSchool.name) - 1);
stSchool.cnt = 1;
strncpy(stTeacher.name, "Teacher", sizeof(stTeacher.name));
stTeacher.id = 1;
}
如何在得知 school 的情况下得到 teacher 的信息呢?你或许可以这么做:在 School 中新增 Teacher 的指针变量,使其指向 teacher。
typedef struct School
{
char name[10]; /* 校名 */
int cnt; /* 教职工个数 */
struct Teacher *pstTeacher; /* 【Add】指向 Teacher 的指针变量 */
}SCHOOL_S;
int main()
{
Init();
stSchool.pstTeacher = &stTeacher;
}
这也不失为一种方法,但怎么样才能用到第一个成员变量的「双重身份」这个信息呢?
下面让我们对结构体 School 和 Teacher 做个简单修改:
typedef struct List
{
struct List *next;
}LIST_S;
typedef struct Teacher
{
LIST_S head; /* 【Add】单链表头结点 */
char name[10]; /* 姓名 */
int id; /* 职工编号 */
}TEACHER_S;
typedef struct School
{
LIST_S head; /* 【Add】单链表头结点 */
char name[10]; /* 校名 */
int cnt; /* 教职工个数 */
}SCHOOL_S;
int main()
{
Init();
stSchool.head.next = &stTeacher.head;
TEACHER_S *pstTeacher = (TEACHER_S *)stSchool.head.next;
printf(" stTeacher 的地址为[%p]\n", &stTeacher);
printf("pstTeacher 的地址为[%p]\n", pstTeacher);
return 0;
}
输出结果如下:
是不是很神奇~
最新文章
- iOS CoreData 的级联删除等操作
- main方法执行之前,做什么事
- 开发设计模式(五)单例模式(Singleton Pattern)
- 用USB安装Linux系统(centos7)
- php 问答
- Laravel的ORM入门
- Prince2学习有感:PRINCE2项目管理到底是什么?
- ar1220f-s四条拨号光纤做的策略路由实现负载均衡
- linux JDK或JRE安装或配置
- 关于px,分辨率,ppi的辨析
- Zynq启动流程
- GIT的前世今生
- elasticsearch 一、环境配置
- Codeforces Round #486 (Div. 3) E. Divisibility by 25
- Adobe Photoshop CC 2019画板背景色白底如何去掉?
- input 滑块功能range javascript方法使用
- 学习笔记之The Intelligent Investor, Rev. Ed
- EZ 2018 03 23 NOIP2018 模拟赛(五)
- Python 数据结构与算法——冒泡排序
- VB ASP 使用 now() 时默认格式调整方法