关于MISRA规则 18.4 不允许使用联合体
以下是《嵌入式C 标准研究报告》中关于MISRA对联合体的使用约束说明 <br /><br />规则 18.4 不允许使用联合体 <br />这事一个不太近情理的规定,在具体阐述为何MISRA-C:2004如此痛恨联合体之前,首先需要明确与联合体相关的细节: <br /> 1)联合体的末尾有多少个填充单元 <br /> 2)联合体的各个成员如何对齐 <br /> 3)多字节的数据类型高低字节如何排放顺序 <br /> 4)如果包含位字段 (bit-field),各位如何排放 <br /><br /> 针对细节3举个例子 <br /> 程序段2.1 <br /><br />typedef union{ <br /> uint32_t word; <br /> uint8_t bytes; <br />}word_msg_t; <br /><br />uint32_t read_msg(void) <br />{ <br /> word_msg_t tmp; <br />/* tmp.byte 对应于tmp.word的高8位 <br /> tmp.byte对应于tmp.word的次高8位,依此类推 */ <br /> tmp.bytes = read_byte(); <br /> tmp.bytes = read_byte(); <br /> tmp.bytes = read_byte(); <br /> tmp.bytes = read_byte(); <br /> return (tmp.word); <br />} <br /><br /><br />以上代码在各种通信协议中使用的频率很高,接收端接收到的数据一般都以字节为单位存放,主控程序需要根据相应的协议将接受到的多个字节进行组合。为了实现相同的功能,MISRA-C:2004推荐恶劣read_msg()函数的另外一种写法. <br /><br />程序段2.2 <br /><br />uint32_t read_msg(void) <br />{ <br /> uint32_t word; <br /> word = ((uint32_t)read_byte() ) < < 24; <br /> word = word | (((uint32_t)read_byte()) < < 16); <br /> word = word | (((uint32_t)read_bytes()) < < 8); <br /> word = word | ((uint32_t)read_byte()); <br /> return (word); <br />} <br />无论从程序的可读性还是从执行效率来讲,程序段2.1都要优于程序段2.2。然而,程序段2.1在Intel 80x86/Pentium体系(little-endian,存储多字节整数的时候低位字节存放在低地址)CPU和在Motorola 68K体系(big-endian)中的执行结果完全不一样。假设read_byte()函数返回的数据依次是0x01,0x02,0x03,0x04,则在Intel体系中,程序段2.1 read_msg返回的值是0x4321,在Motorola体系中,返回的则是0x1234. 无论在Intel体系还是在Motorola体系中,程序段 2.2 中read_msg的返回值都是0x1234 <br /><br />这样的话在处理通信协议的时候真的是很麻烦了,比如我要写一个TCP/IP协议斩,不让用联合,也不让用指针类型转换??!!有什么更好的方法么??是啊,需要自己控制endian的时候比较麻烦
我一般是限制使用联合体
在两种情况下,我会使用联合体:<br />union aaa<br />{<br /> 成员A;<br /> 成员B;<br />};<br />1、联合体内各成员不交互解释的情况,即某联合变量,要么只按成员A访问,要么只按成员B访问,中间没有交叉。例如:<br />//用于信号量和互斥量共享内存池<br />union lock_mem_block<br />{<br /> struct semaphore sem;<br /> struct st_mutex mut;<br />};<br />如果某个锁被作为信号量创建,则永远按信号量访问,如果作为互斥量创建,则永远按互斥量访问。<br /><br />2、数据的内容只按其中一个成员解释,包括隐含的和明示的解释。例如<br />union file_attrs<br />{<br /> uint8_t all;<br /> struct file_attr_bits bits;<br />};<br />其中all成员仅仅用于把所有位清零或者置1,不对位成员的存储位置做任何解释。我也不能理解
MISRA是关于可靠性的,是个经验性的东西
就象前人说“轻诺者必寡信”,这不是个规律,但你依循它,会有潜在的好处。<br /><br />MISRA也一样,你也可以不遵守,但遵守了,在某些时候,会显现出它的好处。<br /><br />关于联合体,个人猜想可能有两个方面,一是在不同的编译器、不同体系CPU之间移植代码的时候,有可能遇到问题;另外,从联合体的使用上,如a.b.c, a.c.d,代码阅读者无法直观地区分是结构还是联合体,在大项目中,同一段代码由不同的开发人员来共同维护的时候,有可能导致潜在的混淆。<br />和goto一个道理,看你怎么用了。做底层没有goto怎么行……
底层核心的代码几乎不存在移植的问题……
goto处理异常还是很灵活的
页:
[1]