用 C 编写安全标记联合

2024-03-18

假设你正在写一个C struct它代表一顿饭中的一道菜。课程领域之一struct属于类型:

enum TP_course {STARTER, MAINCOURSE, DESSERT};

然后,根据课程的类型,您有一个子类型:

enum TP_starter {SALAD, GRILLEDVEGETABLES, PASTA};
enum TP_maincourse {BEEF, LAMB, FISH};
enum TP_dessert {APPLEPIE, ICECREAM, MOUSSE};

鉴于一次只会使用其中一个枚举(取决于课程的类型),因此将它们聚合在一个union:

union U_subtype {
   enum TP_starter s;
   enum TP_maincourse m;
   enum TP_dessert d;
};

所以课程struct看起来像这样:

struct S_course {
   enum TP_course type;
   union U_subtype stype;
   float price_in_USD;
   int availability;
   ...and all the rest of data would follow...
};

好的,一切都清楚了,但是...我可以遵循任何编码策略来尝试强制安全访问stype上面标记了联盟?也许以某种方式使其不透明?

例如,如果我写一个switch/caseenum我忘记写一个case对于一个值,编译器会触发警告,这对于以后维护代码有很大的帮助。但如果我访问stype.s无需先检查是否type==STARTER,编译器不够聪明,无法实现有风险的编码,并且根本不会发出警告。

我能否以某种方式组织代码,以便无法访问 的成员U_subtype联盟,除非在一个非常有限的地方,我清楚地记录了必须如何访问这些成员?


经过深思熟虑后,我选择了一种方法,它可以被视为除了 PSkocik 建议的其他三种选择之外的第四种选择:重新设计struct这样就没有类型和子类型,只有子类型。那么该类型不是由struct,但是通过辅助函数。

像这样的事情:

enum TP_course {STARTER, MAINCOURSE, DESSERT};
enum TP_subtype {SALAD, GRILLEDVEGETABLES, PASTA, 
                 BEEF, LAMB, FISH, APPLEPIE, ICECREAM, MOUSSE};

struct S_course {
   enum TP_subtype stype;
   float price_in_USD;
   int availability;
   /*...*/
};

enum TP_course getCourse(struct S_course *c) {
switch(c->stype) {
   case SALAD:
   case GRILLEDVEGETABLES:
   case PASTA:
      return STARTER;
   case BEEF:
   case LAMB:
   case FISH:
      return MAINCOURSE;
   case APPLEPIE:
   case ICE-CREAM:
   case MOUSSE:
      return DESSERT;
   }
}

这种设计保证了对类型的安全读/写访问struct。它会阻止你离开struct在未定义的行为中(例如,将类型设置为 STARTER 但忘记相应地设置子类型),并且它还会阻止您读取(和写入)aunion成员说这不是当前的。

我倾向于更喜欢这种设计风格,并且我承认我受到了 Apple UI 指南的影响:创建一种设计,防止用户输入不支持/未定义的数据;当数据可以集中在一个地方时,切勿将数据分散到不同的地方;从设计中避免荒谬/非法的数据状态,这样您就不需要检查数据是否合法:它总是合法的;每当您可以对单个一般情况执行相同操作时,请避免特殊情况;等等,等等,等等……

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

用 C 编写安全标记联合 的相关文章

  • ROWNUM 的 OracleType 是什么

    我试图参数化所有现有的 sql 但以下代码给了我一个问题 command CommandText String Format SELECT FROM 0 WHERE ROWNUM lt maxRecords command CommandT
  • 创建 DirectoryEntry 实例以供测试使用

    我正在尝试创建 DirectoryEntry 的实例 以便可以使用它来测试将传递 DirectoryEntry 的一些代码 然而 尽管进行了很多尝试 我还是找不到实例化 DE 并初始化它的 PropertyCollection 的方法 我有
  • 如何在C++中实现模板类协变?

    是否可以以这样一种方式实现类模板 如果模板参数相关 一个对象可以转换为另一个对象 这是一个展示这个想法的例子 当然它不会编译 struct Base struct Derived Base template
  • 如何在没有 Control.Invoke() 的情况下从后台线程修改控件属性

    最近 我们遇到了一些旧版 WinForms 应用程序 我们需要更新一些新功能 在专家测试该应用程序时 发现一些旧功能被破坏 无效的跨线程操作 现在 在您认为我是新手之前 我确实有一些 Windows 窗体应用程序的经验 我不是专家 但我认为
  • 如何针对 Nancy 中的 Active Directory 进行身份验证?

    这是一篇过时的文章 但是http msdn microsoft com en us library ff650308 aspx paght000026 step3 http msdn microsoft com en us library
  • c 中的错误:声明隐藏了全局范围内的变量

    当我尝试编译以下代码时 我收到此错误消息 错误 声明隐藏了全局范围内的变量 无效迭代器 节点 根 我不明白我到底在哪里隐藏或隐藏了之前声明的全局变量 我怎样才能解决这个问题 typedef node typedef struct node
  • .Net Core / 控制台应用程序 / 配置 / XML

    我第一次尝试使用新的 ConfigurationBuilder 和选项模式进入 Net Core 库 这里有很多很好的例子 https docs asp net en latest fundamentals configuration ht
  • 为什么模板不能位于外部“C”块内?

    这是一个后续问题一个答案 https stackoverflow com questions 4866433 is it possible to typedef a pointer to extern c function type wit
  • 在 ASP.Net Core 2.0 中导出到 Excel

    我曾经使用下面的代码在 ASP NET MVC 中将数据导出到 Excel Response AppendHeader content disposition attachment filename ExportedHtml xls Res
  • 使用安全函数在 C 中将字符串添加到字符串

    我想将文件名复制到字符串并附加 cpt 但我无法使用安全函数 strcat s 来做到这一点 错误 字符串不是空终止的 我确实设置了 0 如何使用安全函数修复此问题 size strlen locatie size nieuw char m
  • 如何在 Team Foundation 上强制发表有意义的签入评论?

    我有一个开发团队有一个坏习惯 他们写道poor签入评论 当我们必须在团队基础上查看文件的历史记录时 这使得它成为一场噩梦 我已经启用了变更集评论政策 这样他们甚至可以在签到时留下评论 否则他们不会 我们就团队的工作质量进行了一些讨论 他们很
  • 线程、进程和 Application.Exit()

    我的应用程序由主消息循环 GUI 和线程 Task Factory 组成 在线程中我调用一些第三方应用程序var p new Process 但是当我调用Application Exit 在消息循环中 我可以看到在线程中启动的进程仍在内存中
  • 更改窗口的内容 (WPF)

    我创建了一个简单的 WPF 应用程序 它有两个 Windows 用户在第一个窗口中填写一些信息 然后单击 确定 这会将他们带到第二个窗口 这工作正常 但我试图将两个窗口合并到一个窗口中 这样只是内容发生了变化 我设法找到了这个更改窗口内容时
  • 用 C 实现 Unix shell:检查文件是否可执行

    我正在努力用 C 语言实现 Unix shell 目前正在处理相对路径的问题 特别是在输入命令时 现在 我每次都必须输入可执行文件的完整路径 而我宁愿简单地输入 ls 或 cat 我已经设法获取 PATH 环境变量 我的想法是在 字符处拆分
  • C 中的位移位

    如果与有符号整数对应的位模式右移 则 1 vacant bit will be filled by the sign bit 2 vacant bit will be filled by 0 3 The outcome is impleme
  • 检查 url 是否指向文件或页面

    我们需要以下内容 如果文件确实是文件 则从 URL 下载该文件 否则 如果它是一个页面 则什么也不做 举个简单的例子 我有以下命令来下载文件 My Computer Network DownloadFile http www wired c
  • 将应用程序从 Microsoft Access 迁移到 VB 或 C#.NET

    我目前正试图说服管理层需要将我们的应用程序之一移植到 NET 该应用程序已经发展成为 Access 中的一个庞然大物 SQL 后端 拥有 700 个链接表 650 个表单 子表单 130 个模块和 850 个查询 我几乎知道这样做的所有主要
  • 在Linux中使用C/C++获取机器序列号和CPU ID

    在Linux系统中如何获取机器序列号和CPU ID 示例代码受到高度赞赏 Here http lxr linux no linux v2 6 39 arch x86 include asm processor h L173Linux 内核似
  • 在 ASP.NET 中将事件冒泡为父级

    我已经说过 ASP NET 中的层次结构 page user control 1 user control 2 control 3 我想要做的是 当控件 3 它可以是任何类型的控件 我一般都想这样做 让用户用它做一些触发回发的事情时 它会向
  • 为什么 strtok 会导致分段错误?

    为什么下面的代码给出了Seg 最后一行有问题吗 char m ReadName printf nRead String s n m Writes OK char token token strtok m 如前所述 读取字符串打印没有问题 但

随机推荐