本帖最后由 XIANSir 于 2011-3-14 17:51 编辑
最近调试STM32的SD卡、FAT16程序遇到一些比较别扭的事情,虽然不是不知道怎么解决,但就是觉得感觉怪怪的,总感觉这样解决不舒服。
1、第一个问题是关于枚举类型定义的
程序编译时报错: error: #101: "TRUE" has already been declared in the current scope
经过查找,发现问题产生的原因是:
在fatfs模块的integer.h中有如下定义:
typedef enum {FALSE = 0,TRUE}BOOL;
同时在STM32官方固件库的头文件stm32f10x.h中有如下定义:
typedef enum {FALSE = 0, TRUE = !FALSE} bool;
于是问题就来了:在同一个工程下,有两个地方定义了FALSE和TRUE,于是就发生了重复定义。
问题倒也不是太难解决,只要将两个地方的定义其中一个做一些稍微的改变,以区分开来就可以了,比如,将fatfs模块的integer.h中的定义改为:typedef enum {F_FALSE = 0,F_TRUE}BOOL;
然后再把所有用到这个枚举变量的地方都把FALSE和TRUE分别改为F_FALSE和F_TRUE就可以了。
可是总感觉这样不太好,首先,这两个模块都不是我自己写的,而我现在却要去修改别人模块化的代码,而且修改仅仅是因为重复定义的语法问题,而不是为了对代码进行针对性的优化
另外,这里仅仅涉及到两个模块,而且fatfs模块中使用TRUE和FALSE的地方并不多,假如我的代码中使用了七八个来自不同途径的模块,并且都为了方便进行了上面类似的定义,而且每个模块中又大量使用TRUE和FALSE的话,那就要进行大量的纯体力的替换工作,这实在不是一种好的编程习惯。
与之相似的还有typedef问题,为了代码更加的易读,一般比较规范的代码模块都会进行如下的定义:
typedef unsigned int ui32;
如果程序中使用了来自不同途径的功能模块的话,很难保证不会产生类型重复定义而撞车,到时候大量的体力劳动恐怕再次不可避免。
2、第二个问题关于STM32官方片级支持库结构体变量定义的问题
GPIO_InitTypeDef GPIO_InitStructure;
比如上面的结构体变量定义,如果把这个定义放在函数中定义成局部变量,就会造成频繁分配大量临时变量并导致程序堆栈变大,另外如果多个函数中使用了此结构体变量,这个问题就会更加的突出,而且没办法对此结构体变量的部分取值进行保存和传递,导致频繁赋值和出栈入栈操作,降低系统性能。
如果将此结构体变量的定义放在函数外部,定义成全局变量,又有可能导致变量重复定义问题——因为不同的文件可能都要使用此结构体变量。
倒是可以通过加static关键字解决这个问题,比如:
static GPIO_InitTypeDef GPIO_InitStructure;
或者,可以把所有用到的结构体变量定义都统一放在一个.c文件中进行定义,然后在相应的.h文件中进行外部变量声明:
extern static GPIO_InitTypeDef GPIO_InitStructure;
然后通过包含此.h文件来使用此结构体变量。
这种方法好是好,但是,在多任务环境下(使用了RTOS)或者在中断和程序中同时使用此结构体变量又要特别小心。在这种情况下,看来使用static GPIO_InitTypeDef GPIO_InitStructure;定义更加方便了。
尽管这个问题显得很不值一提,但是这却是实实在在的问题,因为我发现,对于ARM CM3的芯片,厂家越来越倾向于提供片级支持库进行编程了,这好像是一种趋势。
3、第三个问题,我很想问一下,前辈以及大侠们,你们会在.h文件中使用#inclued来包含其他的.h文件吗这是一种好的编程习惯吗??
这个问题在有些人看来更加不是一个问题了——想怎么放怎么放,但是我却觉得这实在是一个有关最佳编程实践的问题,良好的习惯必将在未来的程序维护中显现它的益处。
因为.h文件其实是功能模块的接口,而#include实际上决定了模块的依赖关系,这肯定是一个关键的问题——只是一种感觉,因为我编写的代码毕竟还很少,没有更深的体会。
嗯,看来只好慢慢实践,从实践中进行比较,对这些烦人的问题找到最合自己习惯的编码方式。
|