一、双重身份

如下定义了一个 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;
}

输出结果如下:

是不是很神奇~

最新文章

  1. iOS CoreData 的级联删除等操作
  2. main方法执行之前,做什么事
  3. 开发设计模式(五)单例模式(Singleton Pattern)
  4. 用USB安装Linux系统(centos7)
  5. php 问答
  6. Laravel的ORM入门
  7. Prince2学习有感:PRINCE2项目管理到底是什么?
  8. ar1220f-s四条拨号光纤做的策略路由实现负载均衡
  9. linux JDK或JRE安装或配置
  10. 关于px,分辨率,ppi的辨析
  11. Zynq启动流程
  12. GIT的前世今生
  13. elasticsearch 一、环境配置
  14. Codeforces Round #486 (Div. 3) E. Divisibility by 25
  15. Adobe Photoshop CC 2019画板背景色白底如何去掉?
  16. input 滑块功能range javascript方法使用
  17. 学习笔记之The Intelligent Investor, Rev. Ed
  18. EZ 2018 03 23 NOIP2018 模拟赛(五)
  19. Python 数据结构与算法——冒泡排序
  20. VB ASP 使用 now() 时默认格式调整方法

热门文章

  1. bat-配置环境变量2-给PATH追加环境变量
  2. Mybatis-Plus介绍
  3. NC25043 [USACO 2007 Jan S]Protecting the Flowers
  4. 一文讲明白K8S各核心架构组件
  5. Lepton 无损压缩原理及性能分析
  6. 零基础学Java(4)字符串
  7. 『现学现忘』Git后悔药 — 29、版本回退git reset --mixed命令说明
  8. Kubuntu安装字体
  9. [原创]树莓派CM4配置GPIO复用为i2c
  10. 基础算法学习以及$STL$的使用