1. #define
c语言中的预处理命令,用于宏定义。
示例:
#define number 0xff(不用加分号)
这里就是用number代替了0xff。
2. #ifdef
条件编译,满足条件时对下面的程序进行编译,否则不编译。
格式:#ifdef 标识符
程序1(如果标识符是有定义的就编译程序1)
#else
程序2(如果标识符是没有定义的就编译程序2)
#endif
示例:
#define number
#ifdef number
void module1
{
;
}
#else
void module2
{
;
}
#endif
上面的程序开头标识符number被定义过,所以module1不会被编译,会编译module2。
#ifdef number
void module1
{
;
}
#else
void module2
{
;
}
#endif
这里number没有被定义过,所以module1会被编译,而module2不会被编译。
#ifdef与if…else …的区别:#ifdef是决定程序会不会被编译,编译,编译!而if…else…是决定语句是否执行(无论执不执行都被编译过)。
还有一个#ifndef,刚好和#ifdef相反,是没有定义过的标识符会被编译。
3. typedef
对一个类型的关键词重新定义一个别名,用于简化长的变量类型关键词。
示例:
typedef unsigned int uint;(要加分号)
这里就是用uint代替了unsigned int。
typedef和define是用区别的:define只是简单的替换,无论什么都能替换,而typedef替换一些有类型的标识符,如int,int*。。。
typedef (int*) example1;
#define example2 int*
example1 a,b;
example2 c,d;
上面的程序,虽然都是替代了int*,但是有差别的。example1 a,b;表示定义了两个整型变量的指针;而example2 a,b;表示定义了一个整型变量指针和一个整型变量。
4. extern
用于全局变量的申明,extern可以对不是同一个文件的全局变量或函数进行申明,告诉编译器去其他文件找变量或者函数的定义。extern申明变量可以多次,但是变量的定义只有一次。
文件module1.c
int a;在模块1文件中声明了一个全局变量a
文件module2.c
extern int a;声明a在其他文件被定义
a=10;
用include引用头文件和用extern没什么太大区别,但是如果有多个extern申明,一般会写到.h文件,用include包含进来。
另外说明:为了防止.h文件多次被include引用,一般不在.h文件里定义变量和函数,只用来申明变量和函数。变量和函数的定义一般写在.c文件里,然后用.h包含进来。
5. static
用来申明局部变量存储在静态存储区,函数结束时不会被释放。
void module1()
{
static int a;
}
这里a虽然是局部变量,但函数结束后也不会被释放。如果一个有静态变量的函数被调用多次,静态变量只会初始化一次。
void module1()
{
static int a=0;
a++;
printf("%d",a);
}
void module2()
{
static int a=0;
a++;
printf("%d",a);
}
要是上面的程序被调用了两次,那么module1中的printf打印出来的是0和1;而module2打印出来的是0和0。
注意:静态变量是存储类型是全局的,但它仍有作用域的概念,在函数中声明static变量,它的作用域是局部的,但它的存储类型是全局,整个程序在编译过程就为它分配好空间了。最好不要定义全局变量,可以用静态局部变量传值。static申明的函数作用域仅限于当前的文件,其他无法用。
6. __weak
在使用STM32的hal库的时候,我们常常可以看到很多库自带的函数有很多是使用__weak修饰的。
在这里插入代码片
weak 顾名思义是“弱”的意思,所以如果函数名称前面加上__weak 修饰符,我们一般称这个函数为“弱函数”。加上了__weak 修饰符的函数,用户可以在用户文件中重新定义一个同名函数,最终编译器编译的时候,会选择用户定义的函数,如果用户没有重新定义这个函数,那么编译器就会执行__weak 声明的函数,并且编译器不会报错。
.