阅读STM32-hal库代码得到的几点C代码编程规范
阅读STM32-hal库代码得到的几点C代码编程规范
规范一:
头文件使用
#ifndef _XXX_H
#define _XXX_H
#ifdef __cplusplus
extern "C" {
#endif
// 头文件内容
#ifdef __cplusplus
}
#endif
#endif
在C++编译环境中,会定义
__cplusplus
宏,如果在C++代码中需要使用C语言的函数和变量,就需要使用extern "C" {...}
将C语言的代码放在花括号中,表示其中的代码需要按照C语言的规则进行编译。如果在C语言环境中,没有
__cplusplus
宏,所以就不会使用extern "C" {...}
,所有代码都会按照C语言的规则进行编译。
在.h头文件中一般会有以下内容:
- 包含另外一些头文件
- 进行typedef结构体类型的定义
- 进行enum枚举体类型的定义
- 宏定义#define
- 函数声明(供其他.c文件调用)
- extern一些全局变量(供其他.c文件调用)
规范二:
在c文件中只放对应的h头文件,其他需要的头文件都包含在自己的头文件中。
规范三:
c文件中定义的全局变量如果需要让别的文件引用,就将该变量以extern的方式放在对应头文件中。别的文件如果需要使用这个全局变量,就包含该头文件即可。
规范四:
函数前面加上static,说明该函数只在该文件中使用,即为私有函数。在当前c文件的最前面声明该static函数即可。(供当前c文件调用)
规范五:
对于函数来说,默认为extern。加不加extern是等价的。除非使用static关键字,否则一般函数声明都默认为extern。
规范六:
使用#define的方式定义函数很常见。
对于宏定义,保险的做法是不仅应在参数两侧加括号,也应在整个字符串外加括号。
/**
* @brief Clear ADC error code (set it to no error code "HAL_ADC_ERROR_NONE").
* @param __HANDLE__ ADC handle
* @retval None
*/
#define ADC_CLEAR_ERRORCODE(__HANDLE__) ((__HANDLE__)->ErrorCode = HAL_ADC_ERROR_NONE)
规范七:
使用枚举类型一般是定义一些状态值。作为函数的返回类型。
规范八:
如果函数需要传入结构体,则一般是传入结构体指针,这样传参更加快速。
规范九:
变量的命名:驼峰命名法
规范十:
弱函数定义
__weak void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
/* Prevent unused argument(s) compilation warning */
UNUSED(GPIO_Pin);
/* NOTE: This function should not be modified, when the callback is needed,
the HAL_GPIO_EXTI_Callback could be implemented in the user file
*/
}
__WEAK也是一个宏,被定义成了如下:
#ifndef __WEAK
#define __WEAK __attribute__((weak))
#endif
用户可以在用户文件中重新定义一个同名函数,最终编译器编译的时候,会选择用户定义的函数,如果用户没有重新定义这个函数,那么编译器就会执行__weak声明的函数,并且编译器不会报错。所以我们可以在别的地方定义一个相同名字的函数,而不必也尽量不要修改之前的函数。