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; /* 违规 - 此语句肯定不可达 */
}
相关推荐
她似晚风般温柔7899 分钟前
Uniapp + Vue3 + Vite +Uview + Pinia 分商家实现购物车功能(最新附源码保姆级)
开发语言·javascript·uni-app
咩咩大主教10 分钟前
C++基于select和epoll的TCP服务器
linux·服务器·c语言·开发语言·c++·tcp/ip·io多路复用
时光飞逝的日子16 分钟前
多重指针变量(n重指针变量)实例分析
c语言·指针·多重指针·双重指针·n重指针·指针变量
FuLLovers40 分钟前
2024-09-13 冯诺依曼体系结构 OS管理 进程
linux·开发语言
everyStudy2 小时前
JS中判断字符串中是否包含指定字符
开发语言·前端·javascript
luthane2 小时前
python 实现average mean平均数算法
开发语言·python·算法
Ylucius2 小时前
动态语言? 静态语言? ------区别何在?java,js,c,c++,python分给是静态or动态语言?
java·c语言·javascript·c++·python·学习
LvManBa2 小时前
Vue学习记录之六(组件实战及BEM框架了解)
vue.js·学习·rust
凡人的AI工具箱2 小时前
AI教你学Python 第11天 : 局部变量与全局变量
开发语言·人工智能·后端·python