GJB-8114标准是一部嵌入式软件安全测试相关的国家标准,它包括声明定义、版面书写、指针使用、分支控制、跳转控制、运算处理、函数调用、语句使用、循环控制、类型转换、初始化、比较判断、名称、符号与变量使用等多个方面的规定和要求。这些规则是为了保证软件在整个发展过程中的安全性,经过总结归纳而来的强制性规则,旨在提高代码的质量和可靠性,减少潜在的错误和风险。通过GJB-8114标准,可以帮助我们学习嵌入式软件的测试方法,实验室申请CNAS相关领域的相关资质时也会用到该标准。今天我们继续为大家介绍GJB-8114系列内容中的名称、符号与变量使用类规则。
名称、符号与变量使用类
这类一共有16条,实际上是涉及到一些命名规则的标准。
R-1-13-1
禁止局部变量与全局变量同名

比如说违背示例中,有一个全局变量,那么我们的局部变量就不允许再使用这个。这个局部变量还包括什么呢?大家一定要记住还包括里面的参数,也就是说这个参数也不允许与全局变量同名。
R-1-13-2
禁止函数形参与全局变量同名

这个违背示例中展示的很清楚了,就不解释了。
R-1-13-3
禁止函数与全局变量同名

现在好像很少这样做了,原来很多人做加解密的时候,定义一个变量,给它分配一个空间,自己装入二进制码,然后直接把程序都控制成相应的变量,这个变量就跟子程序就一样了,这个时候你就分不清到底是子程序还是变量,所以会要求不能同名。
R-1-13-4
禁止变量与标识同名

我们定义了很多的类型、结构,给它取了一些的标识,然后定义的变量跟这个标识重名了,是不允许这样的。尽管有时候不会出问题,但是也是不允许的。
R-1-13-5
禁止变量与枚举同名

这个变量跟枚举里的某一个元素同名也是不允许的。
R-1-13-6
禁止用自定义关键字做为变量名

像违背示例中展示的,你定义了一种关键字,把某一种类型定义成了自己比较熟悉的名字,然后又把它做成了变量名,这是不允许的。
R-1-13-7
禁止在模块内部重定义变量

这个在C++中这样写有可能不会出问题,编译也不会出问题。但是C++中有一个作用域的概念,不同的乘积里面,可以多次定义这个变量。现在有的编译器已经对这种情况进行了限制,要求不能重复定义。
还有一个问题,在这里要引申一下。通常咱们学C++的人,书上会告诉你,用一个变量的时候,尽量离我们用的最近的地方定义这个变量,但是现在咱们的规则里规定,所有的变量都在函数头上定义,都在前面定义,后面可以用。你有可能在一个函数前面定义一个变量,在一个两三百行的函数中最后几行才用到这个变量,这也是有可能的。
R-1-13-8
禁止仅依赖大小写区分的变量

比如说违背示例中展示的,就是大小写不一样,实际上C语言是可以区分这种不同的变量的,但是汇编不能区分它们的不同,认为它俩是一个。
R-1-13-9
禁止仅依赖小写字母"l"与数字"1"区分的变量

这个是说,有可能你是看不出来你定义的是1还是l,像违背示例中定义了一个a1,定义了一个al,这样你在后面用的时候,就有可能把它用混了。
R-1-13-10
禁止仅依赖大写字母"O"与数字"0"区分的变量

像违背示例中展示的,在咱们的计算机中,这样写你可能有时候根本就分不清楚它到底是0还是O。
R-1-13-11
禁止单独使用小写字母"l"或大写字母"O"作为变量名

为什么单独提出这两个字母呢,最主要的原因是一个太像1了,一个太像0了。
R-1-13-12
程序外部可改写的变量,必须使用volatile类型说明

这个通常的情况是,有一个变量,它就是一个硬件的地址,里是由硬件来驱动的,一直在修改它,这时候,你定义这个地址作为一个变量的时候,应该用volatile类型。这样才能确保在你用到这个变量的时候,它都会从内存中取数。
否则它有可能是将这个变量的值,放在一个寄存器里面,用的时候是从寄存器里取,这个时候虽然你的内存已经变了,但是寄存器里面的并没有变。所以用volatile类型强制地告诉计算机,我用它的时候一定从内存中取。
R-1-13-13
禁止在表达式中出现多个同一volatile类型变量的运算

像违背示例中展示的,flag是一个volatile类型,也就是说它是一个随时变化的量,对它进行运算,再赋给它,这样就会导致内存里的数和缓存里的不一样,因为如果不是这种随时更新的类型,对它进行计算都是放到寄存器中进行计算。这里我们把它从内存中取到寄存器中进行计算时,它有可能变了,就会造成一个很混乱的现象,所以不允许这样做。
R-1-13-14
禁止将NULL作为整型数0使用

NULL通常是我们在头文件中定义的空,往往把它定义成一个0,或者0l等等,不能把它作为整型数使用。这个往往不是我们自己定义的,C语言很多头文件里都对它进行了定义,所以咱们直接引用它并没有什么错误,但是不要把它当作一个数,它往往是一个指针类型。最主要的原因是因为它是一个指针类型,对于指针可以直接赋值,但是对于它就不可以了。
R-1-13-15
禁止给无符号类型变量赋负值

像违背示例中展示的,b是一个整型,可以把它赋成-1。a是无符号的,应该是大于等于0的的数,一旦把这个-1赋给它,就会变成65535,变成了4个f,如果要是32位的,就会变成8个f,就变成了最大数。
R-1-13-16
用于表示字符串的数组必须以'\0'结束

这个是说,你要是对一个char型的数组赋值的话,按照示例中那样赋,最后都得赋全了。像char c[5]="abcd"这样,它本身是一个字符串,这个字符串的意思就是以\0结尾,所以这样赋值是允许的。
整个的强制性规则大致上就是这些,大家在使用的时候要根据实际的情况进行一些取舍,有些强制性的规则会实实在在造成程序运行出问题的,有些可能不会出问题。对于一些非强制性的一些企业,比如说非军工、非宇航的行业,这些强制性的规则可能就不是完全适用,但是如果设计到一些军工、宇航等,这些强制性规则还是要遵守的,如需嵌入式软件代码测试作业指导书可私信我交流。
本系列内容整理自优品软件培育计划百场前沿技术系列讲座直播第16期,中国航天科技集团公司软件评测中心研究员李国良为大家带来的《白盒测试------C/C++编程规范》专题讲座,他曾参与过多个大型航空、航天、军工、电子型号项目的测试任务,如需直播回放视频也可私信我获取。
(谢绝转载,更多内容可查看我的专栏)