C语言再学习 -- 编程规范

C语言编程规范这部分一直想总结一下。现在终于付诸行动了。

其实之前讲过一些面试题,参看:嵌入式面试知识点总结 -- C语言篇

里面已经有包含一部分了,比如《高质量C++ C编程指南》.林锐着.pdf。

此次主要参考 华为技术有限公司c语言编程规范MISRA C2012 再详细讲一下C语言的编程规范。

下载:编程规范

这篇文章主要以MISRA C 2012 中文版为基础,再将华为C语言编程规范融入其中。

看来之前总结两年的 C语言再学习 专栏,又有用武之地了。

一、名词解释

1、声明(declare)和定义(define)

参看:C语言再学习 -- 声明与定义

声明一个变量只是将变量名标识符的有关信息告诉编译器,使编译器"认识"该标识符,但声明不一定引起内存的分配 。而定义变量意味着给变量分配内存空间,用于存放对应类型的数据,变量名就是对相应的内存单元的命名。在C/++程序中,大多数情况下变量声明也就是变量定义,声明变量的同时也就完成了变量的定义,只有声明外部变量时例外。函数类似,声明只是告诉编译器有这个名称、类型的函数,而定义则是函数的真实实现。

简单一句话,定义创建了对象并为这个对象分配了内存,声明没有分配内存

以下这些就是声明

c 复制代码
extern int bar;
extern int g(int, int);
double f(int, double); // 对于函数声明,extern关键字是可以省略的。
class foo; // 类的声明,前面是不能加class的。

与上面的声明相应的定义如下:

c 复制代码
int bar;
int g(int lhs, int rhs) {return lhs*rhs;} 
double f(int i, double d) {return i+d;} 
class foo {};

2、连接/链接(linkage)

参看:C语言再学习 -- 存储类、链接

分为三类,外部连接(链接)(external linkage)、内部连接(链接)(internal linkage)和无连接(链接)(no linkage)。

  • 外部连接(链接)(external linkage):对于变量,即无"static"修饰的全局可访问的变量;对于函数,即无"static"修饰的全局可调用的函数。它们即使没有在头文件中用"extern"做外部声明,仍然被识别为外部连接(链接)(external linkage)。
  • 内部连接(链接)(internal linkage):即由"static"修饰的全局变量和函数,它们尽可在所在文件内访问和调用,无法被全局访问/调用。
  • 无连接(链接)(no linkage):即函数内部变量。所有函数都是有连接(链接,linkage)的。内部变量包含临时变量和静态变量两种,它们的共同特征是均无法在本函数外被访问。

外部链接:

一个具有外部链接的变量可以在一个多文件程序的任何地方使用。

c 复制代码
int n = 5;  /*文件作用域,外部链接,未使用 static */
int main (void)
{
    ...
    return 0;
}

内部链接:

一个具有内部链接的变量可以在一个文件的任何地方使用。

c 复制代码
static int dodgers = 3; /*文件作用域,内部链接,使用了 static ,该文件所私有*/
int main (void)
{
	...
	return 0;
}

空链接:

具有代码块作用域或者函数原型作用域的变量有空链接,意味着它们是由其定义所在的代码块或函数原型所私有的。

c 复制代码
double blocky (double cleo)  
{
	double patcrick = 0.0;    /*代码块作用域,空链接,该代码块所私有*/
	int i;
	for (i = 0; i < 10; i++)
	{
		double q = cleo * i;   /*q作用域的开始*/
		...
		patrick * = q;         
	}                        /*q作用域的结束*/
	return patrick;
}

3、对象(object)

本规范的编制,具有普适性,故会出现如"对象"、"类"这些标准 C 中不提及的概念,对象在 C 语言中的直接对应是变量。当前对象不仅仅是变量,但本译文仅限考虑标准 C(准确的说是嵌入式 C),故不过多描述,我们将其当成"变量"理解即可。

二、规则

每条 MISRA C 准则都可以被归类为"规则"或"指令"。

  • 规则:仅对源代码进行分析,即可对规则进行合规性判定,静态分析工具应该具有判定规则的能力,不需要结合人工判定。
  • 指令:仅对源代码进行分析,无法对指令进行合规性判定,往往需要结合设计文档或开发人员的经验进行综合判定,静态分析工具可能提供辅助,但不同性能的工具提供的解释可能大不相同。

MISRA C2012将规则和指令均分为三个级别:

  • 强制类:必须满足;
  • 必要类:应该满足,若不满足应该说明原因;
  • 建议类:应该满足,若不满足应该说明原因。

1、标准 C 环境(A standard C environment)

Rule 1.1 程序不得违反标准 C 语法和约束,并且不得超出具体实现的编译限制

  • 级别:必要
  • 解读:程序应仅使用所选标准版本中指定的 C 语言及其库的功能
  • 示例:比如你用C90的编译器你就要符合C90的规则和特性,而不能去使用到C11的特性,其实即使你使用了,编译器也不支持,但不一定都能检测出来,具有一定的风险。

Rule 1.2 不应该使用语言扩展

  • 级别:建议
  • 解读:不要用编程语言扩展属性,否则会降低程序的可移植性
  • 示例: if ((NULL != FuncPointer) && (*FuncPointer())),这样的语句是符合语法的,且就是利用了"一旦确定结果立即停止评估"的特性,在 FuncPointer 值为
    NULL 时执行"&&"的右操作数会非常危险,程序会跑到哪完全不可预知。

Rule 1.3 不得发生未定义或严重的未指定行为

  • 级别:必要
  • 解读:一些未定义或未指定的行为有特定的规则处理。此规则意在防止其他未定义和关键的未指定行为。MISRA C 的许多准则旨在避免某些未定义和未指定的行为。 例如,遵守 Rule 11.4、Rule 11.8 和 Rule 19.2 的所有内容可确保在
    C 中不能创建指向使用 const 限定类型声明的对象的非 const 限定指针。这避免了 C90 [Undefined 39]和 C99
    [Undefined 61]。

2、未使用的代码(Unused code)

Rule 2.1 项目不得包含不可达代码(unreachable code)

  • 级别:必要
  • 解读:如果一个程序没有表现出任何未定义的行为,那么无法到达的代码就不能被执行,也不能对程序的输出产生任何影响。因此,无法到达的代码的存在可能表明程序逻辑中的错误。
    无法到达的代码会占用目标机器的内存空间,可能会导致编译器在围绕无法到达的代码传输控制时选择更长的、更慢的跳转指令。而且在循环中,它可以防止整个循环驻留在指令缓存中。
  • 示例:switch中某个case分支是永远运行不到的,程序员应该删除这种代码。
c 复制代码
enum light { red, amber, red_amber, green };
enum light next_light ( enum light c )
{
 enum light res;
 switch ( c )
 {
	 case red:
	 	res = red_amber;
	 	break;
	 case red_amber:
		 res = green;
	 	break;
	 case green:
	 	res = amber;
	 	break;
	 case amber:
	 	res = red;
	 	break;
	 default:
	 {
	 	/* 当参数 c 的值不是枚举型 light 的成员时, 此 default 分支才可达 */
	 	error_handler ( );
	 	break;
	 }
 }
 return res;
 res = c; /* 违规 - 此语句肯定不可达 */
}
相关推荐
Json____2 分钟前
学法减分交管12123模拟练习小程序源码前端和后端和搭建教程
前端·后端·学习·小程序·uni-app·学法减分·驾考题库
五味香6 分钟前
Linux学习,ip 命令
linux·服务器·c语言·开发语言·git·学习·tcp/ip
欧阳枫落12 分钟前
python 2小时学会八股文-数据结构
开发语言·数据结构·python
Chef_Chen15 分钟前
从0开始学习机器学习--Day22--优化总结以及误差作业(上)
人工智能·学习·机器学习
何曾参静谧19 分钟前
「QT」文件类 之 QTextStream 文本流类
开发语言·qt
monkey_meng23 分钟前
【Rust类型驱动开发 Type Driven Development】
开发语言·后端·rust
虾球xz30 分钟前
游戏引擎学习第11天
stm32·学习·游戏引擎
落落落sss31 分钟前
MQ集群
java·服务器·开发语言·后端·elasticsearch·adb·ruby
心怀梦想的咸鱼33 分钟前
Ue5 umg学习(三)文本控件
学习·ue5
心怀梦想的咸鱼34 分钟前
Ue5 umg学习(二)图像控件,锚点
学习·ue5