大家好,我是痞子衡,是正经搞技术的痞子。今天痞子衡给大家讲的是飞思卡尔软件开发C语言编码规范

  2020鼠年春节是个漫长的假期,痞子衡在家百无聊赖,翻出了2016年10月1日(这个时间是痞子衡正式开始用markdown+github写技术文章并发表到博客园上的纪念日)之前写的技术文档,不翻不知道,一翻吓一跳,从2007年上大学开始到2016年这十年间,我真的写了非常多的技术类文章,但都不够完整,没有成系统,排版上也不优雅,底下有时间我会慢慢整理出来,不能让以前的辛苦都被埋没了。

  痞子衡2016年之前所写的那些技术文章除了原创外,也有一些是翻译的,比如今天要分享的这篇就是2013年痞子衡刚入职飞思卡尔半导体MCU软件团队时为了学习C编码规范所翻译的(外企嘛,各种资料都是洋文),当时飞思卡尔刚成立MCU软件团队不久,那时候Kinetis SDK也还没有正式推出,整个团队必须要有一个统一且良好的编码风格,这样写出来的SDK才符合大厂身份。废话不多说,下面是编码规范原文:

1.引言

  制定此编码风格指导手册的目的是为了使按此规范编写出的C/C++代码极易被阅读和理解。

2.与其他编码风格对比

3.基本排版格式

  • 需要以4个空格为单位的缩进.
  • 坚决不用Tab键,要用空格键.
  • 所有文件结尾必须空一行.
  • 文本文件必须用UTF-8编码.
  • 每一行不能超过100个字符.

4.文档与注释

  • 恰当地进行代码注释.
  • 关于注释长度没有具体限制,只要能提供帮助,就尽可能地注释.
  • 注释应该解释代码为什么要这么做,而不是如何去做(代码本身已经表明了如何去做).
  • 选择Doxygen文档系统来完成注释,除了在函数中的注释之外(因为Doxygen不适用于个别代码行的注释),Doxygen也不适用于汇编.

5.标准数据类型

  • 仅使用C99标准给出的整型(定义见stdint.h文件),如uint32_t,int16_t等,不要typedef自己的整型类型,如u8,int_32,WORD等.
  • 使用char 或wchar_t来表示字符串,但二进制缓存仍应使用uint8_t
  • 仅使用C99标准给出的bool型(定义见stdbool.h文件)来表示布尔变量,true和false表示其值. (ps: windows平台下编译时需自行定义,因为windows下不包含stdbool.h文件)

6.标识符的命名

  以下是C/C++下变量、函数、typedef、宏命名的基本规则,命名规则可以接受细微改动,但要保证在同一模块中的一致性:

  • 全局函数名:全小写,单词用下划线隔开

    如:i2c_receive_data()
  • 普通变量名:Camel命名法

    如:thisIsMyVariable
  • 结构体名和类名:Pascal命名法

    如:BigBoxOfTools
  • 类成员函数名:Camel命名法

    如:initialLongProcess()
  • 用typedef重命名:全小写,单词用下划线隔开,加_t后缀

    如:big_box_of_tools_t
  • 用宏命名:单词全大写(仅在宏中使用,且必须使用)

  描述性强的,可读性强的变量名非常重要:

  • 大部分单词都不应该缩写,比如应用block而不是blk,应用count而不是cnt.

    一些流行的缩写还是允许的,如init或config
  • 完全可以接受较长的,描述性的变量名
  • 布尔型变量可以使用”is”,”did”等前缀,这会清晰地表明其是一个布尔型
  • 变量名应该可以表达其目的,但坚决反对匈牙利命名(加数据类型前缀)

    正确: temporaryParameters, startBlock, nodeKey, isAlarmEnabled

    错误:u32BlkNum, bEnabled

  有时候为了表明范围和目的,有些变量命名是可以加前缀和后缀的:

  • 局部变量:无需前缀
  • 全局变量:加g_前缀
  • 静态变量:加s_前缀
  • 类成员变量:加m_前缀
  • 常量:加k前缀

    1):如kUnconstrained, kFirstPage, kMaxBufferBytes

    2):k前缀使常量很容易被识别
  • typedef型变量:加_t后缀

  备注:切记不要用匈牙利命名法,因为其会导致变量名难于阅读,且类型前缀常常会与变量真正类型不同步,微软曾是此命名法的拥趸,但其已意识到此命名法的缺陷,目前正在逐渐脱离此方法。

7.可调试性

  • 一系列的整型常量应该用枚举来表示,而不是用宏来定义

    1):在调试时,常量被显示为真实的标识,而不是数字

    2):便于常量的逻辑分组
  • 大部分情况下,使用内联函数来代替宏功能

    1):在调试中,内联函数可以被禁用,故可以跳过

    2):内联函数参数有类型,而宏中参数不可以有类型

    3):这个规则仅适用于当用宏来表示一段代码时,不适用于在表达式中表示某部分的宏

8. C99标准

  • 需要使用C99

    C99被允许使能C++或C89语义内联
  • 在尽量靠近变量被使用的地方来声明变量,而不是一律在函数顶部声明

    1):这可以很容易地找到变量的定义

    2):可以方便编译器进行优化
  • 单行注释应使用//而不是/* …*/

    1):大部分人认为//式注释方便阅读

    2):免去注释嵌套的烦恼
  • 多行注释/* …*/可以被用作大段确定的内容注释,就像Doxygen注释头一样,以使得被注释的内容突出。

9.内联功能

  头文件中,内联功能启用应用static inline来完成

10. C/C++通用性

  头文件中的公用函数原型必须包含在下列语句中

  1. #if defined(__cplusplus)
  2. extern "C" {
  3. #endif // __cplusplus
  4. // 此处放函数原型
  5. #if defined(__cplusplus)
  6. }
  7. #endif // __cplusplus

  C中一般都用typedef来重命名结构体和枚举数据类型,不要提及原始的结构体或枚举型名

  C++中,则不需用typedef来重命名,直接用原始的结构体或枚举型名;但是如果代码被C/C++共享,则应遵从C风格

  对于被用在C++中的函数(比如类成员)而言,如果函数不带任何参数,则不需要一个专门的void参数来表明,而在C中这是需要的

11.花括号的使用

  花括号的使用虽重要性不高,但经常起争议

  • 通常情况下,花括号应该单独起一行,不需要额外的缩进
  • 有时为了保持可读性,可以不遵守上一规则
  • 花括号使用的关键点在于不要将代码凑在一起,从而使得代码比较难阅读;也不要因为具体格式的限定,从而打破视觉流程

  使用规则可以接受细微改动,但要保证在同一模块中的一致性,以及易于阅读

  1. 结构体和类示例:
  2. struct Monkey
  3. {
  4. int x;
  5. };
  6. typedef struct MonkeyTwo {
  7. int y;
  8. } monkey_two_t;
  9. class Cube
  10. {
  11. public:
  12. Cube(int theSize);
  13. private:
  14. int m_size;
  15. };
  16. 枚举示例:
  17. enum _my_enum
  18. {
  19. kValueOne = 1,
  20. kValueTwo = 2
  21. };
  22. typedef enum _another {
  23. kAnotherOne = 10,
  24. kAnotherTwo = 20
  25. } another_t;
  26. 函数示例:
  27. void foo()
  28. {
  29. printf("hi\n");
  30. }
  31. If语句示例:
  32. if (baz >= kMaximumBaz)
  33. {
  34. baz = kMaximumBaz;
  35. }
  36. else if (!ready)
  37. {
  38. makeItReady();
  39. }
  40. else
  41. {
  42. abort();
  43. }
  44. For语句示例:
  45. for (i=0; i < 10; ++i)
  46. {
  47. printf("%d", i);
  48. }
  49. While语句示例:
  50. while (!done)
  51. {
  52. doSomething();
  53. }
  54. Do-while语句示例:
  55. do {
  56. doSomething();
  57. } while (!done);
  58. Switch语句示例:
  59. switch (value)
  60. {
  61. case 0:
  62. x += 1;
  63. break;
  64. case 1:
  65. {
  66. int y;
  67. calculateIt(&y);
  68. break;
  69. }
  70. default:
  71. return;
  72. }
  73. 命名空间示例:
  74. namespace fsl
  75. {
  76. // Don't indent namespace contents!
  77. }
  78. Try-catch语句示例:
  79. try
  80. {
  81. }
  82. catch (std::exception & e)
  83. {
  84. }
  85. catch (...)
  86. {
  87. }

12. 关于MISRA-C规范

  代码风格基本遵照MISRA-C:20xx规范,但除了以下例外(这些例外是基于MISRA-C:2004规范的)

  至此,飞思卡尔软件开发C语言编码规范痞子衡便介绍完毕了,掌声在哪里~~~

欢迎订阅

文章会同时发布到我的 博客园主页CSDN主页微信公众号 平台上。

微信搜索"痞子衡嵌入式"或者扫描下面二维码,就可以在手机上第一时间看了哦。

痞子衡嵌入式:知名半导体MCU大厂软件开发C代码规范的更多相关文章

  1. 痞子衡嵌入式:恩智浦MCU安全加密启动一站式工具NXP-MCUBootUtility用户指南

    NXP MCU Boot Utility English | 中文 1 软件概览 1.1 介绍 NXP-MCUBootUtility是一个专为NXP MCU安全加密启动而设计的工具,其特性与NXP M ...

  2. 痞子衡嵌入式:借助Serial Plot软件测量i.MXRT系列FlexSPI驱动Flash页编程执行时间

    大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家介绍的是i.MXRT系列FlexSPI驱动Flash页编程执行时间. 痞子衡之前写过一篇文章 <串行NOR Flash的页编程模式对于量产 ...

  3. 痞子衡嵌入式:超级下载算法(RT-UFL)开发笔记(1) - 执行在不同CM内核下

    大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家介绍的是超级下载算法开发笔记(1)之执行在不同CM内核下. 文接上篇 <RT-UFL - 一个适用全平台i.MXRT的超级下载算法设计&g ...

  4. 痞子衡嵌入式:超级下载算法(RT-UFL)开发笔记(2) - 识别当前i.MXRT型号

    大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家介绍的是超级下载算法开发笔记(2)之识别当前i.MXRT型号. 文接上篇 <超级下载算法(RT-UFL)开发笔记(1) - 执行在不同CM ...

  5. 痞子衡嵌入式:超级下载算法(RT-UFL)开发笔记(3) - 统一FlexSPI驱动访问

    大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家介绍的是超级下载算法开发笔记(3)之统一FlexSPI驱动访问. 文接上篇 <超级下载算法(RT-UFL)开发笔记(2) - 识别当前i. ...

  6. 痞子衡嵌入式:超级下载算法(RT-UFL)开发笔记(4) - 轮询Flash配置参数

    大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家介绍的是超级下载算法开发笔记(4)之轮询Flash配置参数. 文接上篇 <超级下载算法(RT-UFL)开发笔记(3) - 统一FlexSP ...

  7. 痞子衡嵌入式:超级下载算法(RT-UFL)开发笔记番外(1) - JLinkScript妙用

    大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家介绍的是超级下载算法开发笔记番外篇之JLinkScript妙用. JLinkScript 文件是配套 J-Link 调试器使用的脚本,这个脚本适 ...

  8. 痞子衡嵌入式:高性能MCU之Media应用开发那些事 - 索引

    大家好,我是痞子衡,是正经搞技术的痞子.本系列痞子衡给大家介绍的是高性能MCU之Media应用开发相关知识. 飞思卡尔半导体(现恩智浦半导体)2017年推出的i.MX RT系列第一款芯片i.MXRT1 ...

  9. 痞子衡嵌入式:高性能MCU之人工智能物联网应用开发那些事 - 索引

    大家好,我是痞子衡,是正经搞技术的痞子.本系列痞子衡给大家介绍的是高性能MCU之人工智能物联网应用开发相关知识. 恩智浦半导体2017年开始推出的i.MX RT系列跨界处理器,这种高性能MCU给嵌入式 ...

随机推荐

  1. win10安装Keras报错处理

    本机已经安装好TensorFlow安装Keras的过程中遇到了些问题,解决后做一下记录: 1.Keras与TensorFlow的关系 Keras默认以TensorFlow为后端,同时可选以Theano ...

  2. Vue通讯

    vue组件通讯 #props传递数据 父->子 //父组件传递数据 <template> <Children :data="msg"></Chi ...

  3. Web基础了解版10-Filter-Listener

    Filter 对于WEB应用来说,过滤器是一个驻留在服务器中的WEB组件,他可以截取客户端和WEB资源之间的请求和响应信息. 在一个WEB应用中可以部署多个过滤器,多个过滤器就组成了一个过滤器链,请求 ...

  4. mysql主从之多元复制

    实验环境: 192.168.132.121   master1 192.168.132.122   master2 192.168.132.123   slave 使用gtid的方式 两个主分别是19 ...

  5. $[SHOI2007]$ 园丁的烦恼 二维数点/树状数组

    \(Sol\) 设一个矩阵的左上角为\((x_1,y_1)\),右下角为\((x_2,y_2)\),\(s_{x,y}\)是到\((1,1)\)二维前缀和,那么这个矩阵的答案显然是\(s_{x_2,y ...

  6. 第 426 期 Python 周刊

    文章,教程和讲座 端到端机器学习:从数据收集到模型部署 链接: https://ahmedbesbes.com/end-to-end-ml.html 在本文中,我们将完成构建和部署机器学习应用程序的必 ...

  7. ECShop二次开发指南(一)

    ECSHOP是一套完整的网络商店解决方案,包括前台的商品展示.购物流程和强大易用的后台管理.由于 ecshop简单易用,使用者几乎可以在3几分钟简单的设置一下就可以拥有一个网上商店系统,所以很多的B2 ...

  8. js获取当前农历时间

    <template> <div class="gaia-header"> <img alt="gaia_logo" src=&qu ...

  9. 「HDU3823」 Prime Friend 解题报告

    Prime Friend Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total S ...

  10. Intellij IDEA2019.1.3破解

    下载 JetbrainsCrack.jar(链接:https://pan.baidu.com/s/1Dkw1PruzBlEMjcYszNlSZA 提取码:2bf7),放到bin目录下(其实位置可以随便 ...