1.了解C语言头文件如何包含巧妙的用法
当一个头文件被多个C文件包含时,并且这些C文件的公共变量都定义在头文件中时,编译时会出现重复定义,导致编译失败。 通常我们会采用以下两种方法来解决问题。 上述问题。 (为了让问题更清楚,我们假设三个C文件C1、C2、C3和一个头文件H1。C1、C2、C3有两个公共变量V1和V2) 1、在C1文件中定义变量V1和V2 V2,在C2和C3文件中对V1和V2使用extern声明; 2、在C1文件中定义变量V1和V2,在H1中对V1和V2使用extern声明,然后在C2和C3文件中包含H1; 很明显,上面两种方法都需要写V1和V2至少两次,一次定义,一次外部声明,而且它们不在同一个文件中。 这不利于管理和修改。 有没有办法放置这些公共变量? 在一个文件中,并且只需要写入一次? 首先,我们将所有要使用的公共变量写入 com.h 文件中。 在定义每个变量之前添加符号 EXT_。 当头文件被main.c函数包含时,定义EXT_为空,表示com.h中的变量是在main.c中定义的。 当包含在其他文件中时,将EXT_定义为extern,表示外部声明,如:Com.h文件:
//避免重复定义
#ifdef根
#定义EXT_
#别的
#定义EXT_外部
#万一
//全局变量EXT_u8变量1;
//该变量在三个C文件Main.c中使用
#define root //在包含com.h之前定义root
#include“com.h”
2. 使用结构体定义总线或外设地址。 当一个整体包含多个不同类型的成员时,通常使用结构体来定义结构体变量,以便内存将这些变量以递增的方式分配给相邻的变量。 地址(错位的地方会有填充),按照“结构体名.成员名”的方法访问结构体中的成员,这就是访问结构体变量的方式; 但还有一个指向结构体变量的指针,可以将地址转换为结构体类型的指针,比如寄存器的定义:(以下摘自STM32固件函数库,关于通用输入输出口)
类型定义结构
vu32 CRL; //0
vu32 CRH; //偏移4
vu32 IDR; //偏移8
vu32 ODR;
vu32BSRR;
vu32 BRR;
vu32LCKR;
} GPIO_TypeDef;
#define GPIOA_BASE ((u32)0x40010800) //GPIOA基址为0x40010800
#定义GPIOA (GPIO_TypeDef *) GPIOA_BASE; //强制类型转换为GPIO_TypeDef类型的指针
这样,在操作GPIOA寄存器时,只需要这样写
读取:X= GPIOA->CRL; 写入:GPIOA->CRL=X; 或阅读:如下:
#定义GPIOA_CRL 0x40010800
#定义GPIOA_CRH 0x40010804
#定义GPIOA_IDR 0x40010808
#定义GPIOA_ODR 0x4001080C
#定义GPIOA_BSSR 0x40010810
#定义GPIOA_LCKR 0x40010814
显然,第一种写法更加形式化,并且在定义多个GPIO时,只需要将其他GPIO的基地址强制转换为该结构类型的指针即可。 我们来看一个定义外部总线的例子:
类型定义结构
vu8 CH375_数据;
vu8 CH375_CMD; //偏移1
CH375_TypeDef;
#定义CH375((CH375_TypeDef *)0x6c000000)
CH375-> CH375_DATA=数据; //写入数据到地址0x6c000000
CH375-> CH375_CMD=cmd; //写入命令到地址0x6c000001
这个怎么样? 是不是方便很多呢? 重要的是代码的查看性和可读性得到了提高。
3. 使用枚举数据类型来定义特定状态。 在实际问题中,有些变量的取值被限制在一个有限的范围内。 例如,一个函数在运行过程中会返回几种具体的状态:操作成功、操作失败、忙等,如果我们在函数中直接用0、1、2来表示这三种状态,有时数值和实际状态可能不一样不匹配,导致状态设置和状态判断错误。 那么我们可以在程序中使用宏或者枚举来提前定义这些状态。
例如:使用宏定义:
#defineSucess 0
#定义失败1
#定义忙2
使用枚举
类型定义枚举
成功 = 0,失败,忙碌
标志状态;
4. 使用union类型定义共享内存空间。 联合类型定义的数据是与多个成员共享同一内存空间。 空间的大小是最大成员的大小。 它的用法与结构体完全相同,但值得注意的是,它不能同时引用多个成员,并且一次只能使用其中一个。 如果程序中有很多全局变量,包括几个结构体和数组,如果这些都定义了,必然会占用大量的内存,也可能导致单片机内存不足。 如果可以在不同的时间使用多个数组和结构体,变量共享一段内存,可以节省大量的内存空间。 例如,如果下面的输入和输出不是同时执行,则它们可以共享相同的内存空间。
联盟
结构体
无符号字符标志;
无符号字符类型;
无符号字符状态;
无符号长 DataLen;
无符号字符缓冲区[64];
}数据输出;
结构体{
无符号字符标志;
无符号字符类型;
无符号字符状态;
无符号长 DataLen;
无符号字符缓冲区[64];
数据输入;
} 中国银行;
C语言博大精深、丰富多彩。 如果使用得好,就能很好地发挥它的作用。 同时,对于一个设计师来说,学习好的编程方法,养成良好的编程习惯也是极其重要的。 以上四点都是我自己积累和学习的一些总结,希望能够与大家交流,共同学习,共同提高。
我们的官方QQ群:281549832
在此感谢大家的大力支持!