博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
再说变体结构 - 回复 "彬" 的问题
阅读量:6279 次
发布时间:2019-06-22

本文共 2723 字,大约阅读时间需要 9 分钟。

  hot3.png

问题来源:

假如有这样三种结构, 分别来描述: 直线、圆与三角形:

type  {描述直线的结构}  TLine = packed record    ID: Integer;    {编号}    x1,y1: Integer; {第一点}    x2,y2: Integer; {第二点}  end;  {描述圆的结构}  TCircle = packed record    ID: Integer;  {编号}    x,y: Integer; {中心点}    r: Integer;   {半径}  end;  {描述三角形的结构}  TTriangle = packed record    ID: Integer;    {编号}    xa,ya: Integer; {a点}    xb,yb: Integer; {b点}    xc,yc: Integer; {c点}  end;//无需 SizeOf, 我们可以轻松看出三个结构的大小分别是: 20、16、28 字节
上面三个结构的数据有类似之处, 在实用中常常需要用一个综合的结构替代它们;
这就像 Delphi 中的 TWMKey、TWMMouse、TWMClose 等近 200 个结构都可以用 TMessage 代替一样.
下面是一个非常不好, 但容易理解的描述:

TMyShape = packed record    ID: Integer;    x1, y1, x2, y2: Integer;    x, y, r: Integer;    xa, ya, xb, yb, xc, yc: Integer;  end;//此结构大小是 56 字节//之所以说它不好是因浪费太多, 譬如记录一个圆, 只需要 ID、x、y、r 四个字段, 会浪费其它 10 个字段.//但如果需要一个结构同时描述一条直线、一个圆、一个三角的话, 这个结构是合适的; 这里讨论的并不是这种情况.
我们在某一时刻只需要它来表示一个形状(或者是直线、或者是圆、或者是三角);
假如我们让结构按照最大的需要分配空间, 譬如三角需要最多(除 ID 外, 是 6*4 个字节), 就分配 24 字节; 这个空间用来记录一个圆或者直线也是足够的.
Delphi 允许我们使用这样的语法来定义(这就是所谓的变体结构):

TMyShape = packed record    ID: Integer;    case Integer of      0: (x1, y1, x2, y2: Integer);      1: (x, y, r: Integer);      2: (xa, ya, xb, yb, xc, yc: Integer); {注意结构成员无论如何是不能重名的}  end;//可以这样查看一下: ShowMessage(IntToStr(SizeOf(TMyShape))); //它刚好是 28 字节, 和上面的 TTriangle 大小一样.//用这个结构可以非常方便地描述上面三种图形; 尽管有时也会有浪费, 但相比在使用时带来的方便, 那是可以接受的.
把上面这种描述用表格表示一下:
共 28 个字节
用于三角时 ID xa ya xb yb xc yc
用于直线时 ID x1 y1 x2 y2
用于圆时 ID x y r
对这样的一个结构变量(譬如是 rec: TMyShape)来讲, 不管你是不是需要, rec.ID、rec.x1 ... rec.yc 等所有结构成员都是存在的;
但有些数据是共享一块内存, 譬如 x1、x、xa 共享 4 个字节; x2、r、xb 共享 4 个字节, 这可以测试一下:

type  TMyShape = packed record    ID: Integer;    case Integer of      0: (x1, y1, x2, y2: Integer);      1: (x, y, r: Integer);      2: (xa, ya, xb, yb, xc, yc: Integer);  end;var  rec: TMyShape;begin  rec.r := 123;  ShowMessageFmt('%d, %d', [rec.x2, rec.xb]); {123, 123}end;
咱们的 "彬" 朋友不明白的是 case Integer of ...
这里的 case 并不是咱们经常用的 case 语句(譬如它没有 end;), 只是 Delphi 的语法规定而已;
case Integer of 中的 Integer 也没有再占用 4 字节的空间(但接下了的例子会占用), 也只是语法形式.
考虑另一个问题: 我们仅从一个结构变量的数据能看出它具体描述的图形类型吗?
应该说: 这不容易看出; 其实, 在实用中我们很少会有这种要求.
假如非要从结构数据中识别图形类型也可以, Delphi 提供了语法支持, 但这又要多占几个字节:

TMyShape = packed record    ID: Integer;    case flag: Integer of      0: (x1, y1, x2, y2: Integer);      1: (x, y, r: Integer);      2: (xa, ya, xb, yb, xc, yc: Integer);  end;//此时的结构大小应该是 32 字节.//像这样, flag 也是一个结构成员, 也可以读写; 我们可以给 flag 赋不同的值以区别图形类型.//但不管 flag 这个值是什么, 都不会影响前面的内存共享机制; flag 也不会因为其他赋值而自动改变.
根据不同的需要, 上面的 flag 也可以是其他类型(譬如枚举);
我也经常见到 case Boolean of 的用法, 这只能用在两种可选状态的情形, 譬如:

TMyShape = packed record    ID: Integer;    case Boolean of      True:  (x1, y1, x2, y2: Integer);      False: (x, y, r: Integer);  end;
Delphi 还有一个相近的概念 absolute(从变量的层面上共享内存), 参见:

转载于:https://my.oschina.net/hermer/blog/320791

你可能感兴趣的文章
数据中心未来的商业化系统
查看>>
《算法技术手册》一2.3 最好、最坏和平均情况下的性能分析
查看>>
LTE-Hi渐行渐近 有望打破4G深度覆盖局限
查看>>
Nuance报告:医护人员如何从人工智能中受益
查看>>
JavaScript异步与Promise实现
查看>>
Android内存泄漏产生的6大原因
查看>>
F5 Networks任命Adam Judd领导亚太区销售工作 将加速区域云和安全业务发展
查看>>
将给企业带来巨大转变的八项“变革式”技术趋势
查看>>
ICML精彩论文:学界与业界联手,通过监测无线信号来判断睡眠阶段
查看>>
欧盟下周或有条件批准微软收购领英
查看>>
指纹识别不安全 美研究人员万能指纹解锁成功率达65%
查看>>
外媒:全球科技进入中美两强时代
查看>>
美国国家安全局在英国运营数据中心从事间谍活动
查看>>
【CVPR 2021主席出炉】谭铁牛、虞晶怡当选,未来4年6位华人主席
查看>>
CRM给企业带来的五大成效
查看>>
继 OpenAI 之后,DeepMind 开源深度学习训练平台 DeepMind Lab
查看>>
雅虎宣布成立研究院取代实验室 两高管离职
查看>>
大数据将如何改变农业
查看>>
《JavaScript和jQuery实战手册(原书第2版)》——第3章为程序添加逻辑和控制
查看>>
Google一年检测出超过76万个恶意网站
查看>>