陈浩师兄03年的一篇博客《用C写有面向对象特点的程序》描述了用C语言来实现类似C++类继承的方法,这样方法的核心要点就是结构体的强制类型转换,让我来简单分析分析C语言中的结构体强制类型转换,还是用陈浩师兄原博的结构体来举例吧。两个结构体如下:

/* 双向链表 (类似于父类)*/
typedef struct hLinks{
struct hLinks *bwLink;
struct hLinks *fwLink;
} hLinks;

/*
* 一个使用双向链表的结构
* (类似于子类)
*/
typedef struct hEnt{
hLinks links;
int hData;
char key[10];
} hEnt;

首先,我们要搞清楚的一点是:C语言中的结构体并不能直接进行强制类型转换,只有结构体的指针可以进行强制类型转换。因此你可以在原博中看到在函数调用的时候有一些比较别扭的参数形式,我们来看看。

/*
* 打印 (类似于子类重载父类的成员函数)
*/
PrintLink( hLinks *h )
{
hEnt *p ; for( p = ( hEnt* ) h->fwLink; /* <-----------把hLink再转回来 */
p != ( hEnt* ) h;
p = ( hEnt* )( (hLinks*)p )->fwLink )
{
printf("hData=[%d], key=[%s]/n", p->hData, p->key);
}
}

PrintLink函数的参数是一个hLinks类型的指针,因此在调用PrintLink时传入参数也应该是hLinks类型的指针,如果我们定义的时候用下面这样的形式。

hLinks head;

那么在调用函数的时候就必须把它转换成hLinks指针,于是先取地址在强制类型转换。

PrintLink( (hLinks *) &head );

这样看起来确实是很别扭,如果我们在声明结构体的时候这样做的话就可以避免这么难看的传递形式。

typedef hLinks *PtrhLinks;

 

话说回来,结构体指针的强制类型转换问题在这里面始终存在。PrintLink中就出现了这样的情况,那么在将hLinks指针转换为hEnt类型指针时有两个问题:

  1. 结构体中的成员情况是怎么的?
  2. 结构体中的成员的值的情况是怎么样的?

首先,结构体是储存在一块连续内存中的,计算机只关心的是结构体的大小和操作方式,结构体大小是定义的时候决定的(要进行对齐),而结构体的操作确实和结构体中的成员类型有关的。指针表示的是内存地址,那么在强制类型转换之后,计算机便以转换后的结构体来看待这个地址内存中的内容。比如两个结构体的内存结构如下:

                  hLinks                         hEnt

*bwLink *bwLink
*fwLink *fwLink
——(未定义) hData
——(未定义) key[10]

 

可以看出,在前两个内存单元中两个结构体存储的内容是相同的,当然不管相不相同计算机是不管的,当hLinks类型转换成hEnt类型时,计算机就将原结构体看做是hEnt类型的。转换后的hEnt类型结构体的前面两个内存单元的内容就是hLinks中的前两个单元内容,而hEnt的后两个内存单元中的内容取得是hLinks后的两个单元(这两个单元不是hLinks类型的成员,而是别的内容,所有如果转换后的hEnt要访问hData和key的话是不安全的!)。

总之一句话,在转换之后,计算机就按照转换后的结构体的组成结构来解释那么一段内存中存储的数据!!

C语言结构体的强制类型转换的更多相关文章

  1. 不可或缺 Windows Native (8) - C 语言: 结构体,共用体,枚举,类型定义符

    [源码下载] 不可或缺 Windows Native (8) - C 语言: 结构体,共用体,枚举,类型定义符 作者:webabcd 介绍不可或缺 Windows Native 之 C 语言 结构体 ...

  2. C/C++语言结构体指针的使用

    C/C++语言结构体指针的使用 主要内容 结构体的使用 - 定义,赋值,结构体指针 结构体作为函数参数的使用 指针的使用 代码内容重点 结构体的使用 - 定义,赋值,结构体指针 结构体作为函数参数的使 ...

  3. Linux C语言结构体-学习笔记

    Linux C语言结构体简介 前面学习了c语言的基本语法特性,本节进行更深入的学习. 预处理程序. 编译指令: 预处理, 宏定义, 建立自己的数据类型:结构体,联合体,动态数据结构 c语言表达式工具 ...

  4. 漫谈C语言结构体struct、公用体union空间占用

    先用代码说话: #include<stdio.h> union union_data0{ int a ;//本身占用4个字节 char b ;//本身占用1个字节 int c ; }; u ...

  5. 解析C语言结构体对齐(内存对齐问题)

    C语言结构体对齐也是老生常谈的话题了.基本上是面试题的必考题.内容虽然很基础,但一不小心就会弄错.写出一个struct,然后sizeof,你会不会经常对结果感到奇怪?sizeof的结果往往都比你声明的 ...

  6. Go语言结构体(struct)

    Go 语言结构体 Go 语言中数组可以存储同一类型的数据,但在结构体中我们可以为不同项定义不同的数据类型. 结构体是由一系列具有相同类型或不同类型的数据构成的数据集合. 结构体表示一项记录,比如保存图 ...

  7. C语言结构体定义的几种方法

    什么是结构体? 在C语言中,结构体(struct)指的是一种数据结构,是C语言中聚合数据类型(aggregate data type)的一类.结构体可以被声明为变量.指针或数组等,用以实现较复杂的数据 ...

  8. 对嵌入式开发C语言结构体的一点总结

    今天冬至居然不上班,公司的良心啊!这回有心情写博客和日志了,好了,废话不多说.直接看下文: 鉴于嵌入式开发过程中,C语言结构体的使用当然是必不可少.话说,基础什么的比你会更牛逼的算法更重要,基础不牢, ...

  9. C语言结构体变量私有化

    操作系统 : CentOS7.3.1611_x64 gcc版本 :4.8.5 问题描述 C语言结构体定义中的变量默认是公有(Public)属性,如果实现成员变量的私有(Private)化? 解决方案 ...

随机推荐

  1. delphi获得当前鼠标坐标

    简单的说就是取鼠标所在位置对应的窗口句柄? procedure TForm1.Timer1Timer(Sender: TObject);vara:TPoint; //用来存放坐标hw:HWND; // ...

  2. HDU 5603 the soldier of love 离线+树状数组

    这是bestcorder 67 div1 的1003 当时不会做 看了赛后官方题解,然后翻译了一下就过了,而且速度很快,膜拜官方题解.. 附上官方题解: the soldier of love 我们注 ...

  3. 交易策略研究 R库

    本文在Creative Commons许可证下发布 交易策略研究 R库,直接安装:xts, TTR,quantmod,RTAQ,PerformanceAnalytics,FactorAnalytics ...

  4. 【译】 AWK教程指南 7AWK应用实例

    本节将示范一个统计上班到达时间及迟到次数的程序. 这程序每日被执行时将读入两个数据文件: * 员工当日到班时间的数据文件 ( 如下列的 arr.dat ) * 存放员工当月迟到累计次数的文件 当程序执 ...

  5. 第二十章、启动流程、模块管理与 Loader

    核心与核心模块 在整个启动的过程当中,是否能够成功地驱动我们主机的硬件配备, 是核心 (kernel) 的工作!而核心一般都是压缩档,因此在使用核心之前,就得要将它解压缩后, 才能加载主内存当中. 另 ...

  6. hdoj 1878 欧拉回路

    欧拉回路 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submis ...

  7. [Objective-c 基础 - 2.2] OC弱语法、类方法

    A.OC弱语法 1.在运行的时候才会检查方法的声明和实现 2.没有声明只有实现的方法也能正常运行,只要在调用之前定义即可 3.类的声明必须存在,否则会出现运行时错误   B.类方法 1.是类名调用的方 ...

  8. Countly在andoid和vps集成使用,开源的统计分析sdk

    这几天项目需要,简单研究了一下countly,说实话完全满足项目需要,比umeng这类产品干净多了. Countly Mobile Analytics 下面就讲一下android 集成的过程,以及 服 ...

  9. MSSQLSERVER数据库- SP_EXECUTESQL的使用

    EXEC和SP_EXECUTESQL有什么区别呢? 1,它们之间最大的区别是嵌入式的参数,如下面一个语句 declare @sql nvarchar() declare @id varchar() ' ...

  10. Linux 下 expect 脚本语言中交互处理常用命令

    Linux 下 expect 脚本语言中交互处理常用命令 1. #!/usr/bin/expect 告诉操作系统脚本里的代码使用那一个 shell 来执行.这里的 expect 其实和 Linux 下 ...