1、/*宏参数及其本身都应加上括号,不加会破坏运算优先级*/
#include "stdio.h"
#include "stdlib.h"
#include "string.h"
/*宏参数及其本身都应加上括号,不加会破坏运算优先级*/
#define MULTI_MACRO(a, b) ( (a) * (b) )
#define MULTI_MACRO_E(c, d) ( c * d )
typedef unsigned int uint32_t;
int main(void)
{
//char a[1000];
uint32_t s_b;
uint32_t s_c;
s_b = MULTI_MACRO (2+3, 2);
s_c = MULTI_MACRO_E (2+3, 2);
//printf("%s", a);
printf("0-%d-0\n", s_b);
printf("1-%d-1\n", s_c);
system("pause");
return 0;
}
2、枚举enum(enumeration)
含义:定义某一个数据类型,这种类型只有某几种可能,在定义的同时将这
些可能一 一例举出来,此种类型就叫枚举。
如下:定义变量Flag为BOOL这种类型,取值为FALSE,
#include "stdio.h"
#include "stdlib.h"
#include "string.h"
typedef unsigned int uint32_t;
enum BOOL{
TRUE, // 错误,没有进行显示赋值
FALSE, // 错误,没有进行显示赋值,且末尾应该没逗号
};
#include "stdio.h"
#include "stdlib.h"
#include "string.h"
typedef unsigned int uint32_t;
enum BOOL{
TRUE = 1, // 正确,进行了显示赋值
FALSE = 0 // 正确,进行了显示赋值,且末尾没逗号
};
调用:
int main(void)
{
enum BOOL flag = FALSE;
if()
{
}
system("pause");
return 0;
}
如下:定义SWITCH类型只有两种取值可能,ON或者OFF。
enum SWITCH{
ENUM_ON = 0x0001U,
ENUM_OFF = 0x1110U,
};
调用:
int main(void)
{
enum SWITCH flag = ENUM_ON;
if()
{
}
system("pause");
return 0;
}
3、C typedef
C 语言提供了 typedef 关键字,我们可以使用它来为类型取一个新的名字,来定义自己的类型。
为什么通常用typedef 定义一个自己要替换的类型?
原因:增加代码的可读性,让人更容易读懂代码。
#include "stdio.h"
#include "stdlib.h"
#include "string.h"
typedef unsigned int uint32_t;
typedef enum {
TRUE = 1, // 正确,进行了显示赋值
FALSE = 0 // 正确,进行了显示赋值,且末尾没逗号
}BOOL;
调用(就省掉了写enum):
BOOL flag = FALSE;
定义与调用:
#include <stdio.h>
#include <string.h>
typedef struct BOOKS
{
char title[50];
char author[50];
char subject[100];
int book_id;
} Book;
int main( )
{
Book book;
strcpy( book.title, "C 教程");
strcpy( book.author, "Runoob");
strcpy( book.subject, "编程语言");
book.book_id = 12345;
printf( "书标题 : %s\n", book.title);
printf( "书作者 : %s\n", book.author);
printf( "书类目 : %s\n", book.subject);
printf( "书 ID : %d\n", book.book_id);
return 0;
}
#define 是 C 指令,用于为各种数据类型定义别名,与 typedef 类似,但是它们有以下不同:
- typedef 仅限于为类型定义符号名称,而#define 除了可以为类型定义别名外,也能为数值定义别名,比如可以定义 1 为 ON。
- typedef 由编译器执行解释的,#define 语句是由预编译器进行处理的。
#include <stdio.h>
#define TRUE 1
#define FALSE 0
int main( )
{
printf( "TRUE 的值: %d\n", TRUE);
printf( "FALSE 的值: %d\n", FALSE);
return 0;
}
4、预编译指令:#ifdef、#ifndef、#else、#endif
条件编译中相对常用的预编译指令。模式如下:
#ifdef ABC
// ... codes while definded ABC
#elif (CODE_VERSION > 2)
// ... codes while CODE_VERSION > 2
#else
// ... remained cases
#endif // #ifdef ABC
#ifdef用于判断某个宏是否定义,和#ifndef功能正好相反,二者仅支持判断单个宏是否已经定义,上面例子中二者可以互换。如果不需要多条件预编译的话,上面例子中的#elif和#else均可以不写。
预编译指令:#if、#elif、#else、#endif
#if 可支持同时判断多个宏的存在,与常量表达式配合使用。常用格式如下:
#if 常量表达式1
// ... some codes
#elif 常量表达式2
// ... other codes
#elif 常量表达式3
// ...
...
#else
// ... statement
#endif
在判断某个宏是否被定义时,应当避免使用#if,因为该宏的值可能就是被定义为0。而应当使用#ifdef或#ifndef。
注意: #if、#elif之后的宏只能是对象宏。如果宏未定义,或者该宏是函数宏,则编译器可能会有对应宏未定义的警告。
总结如下:
1)#if是要判断它后面表达式真假的,是真才执行#if后的代码;
2)#if和#elif搭配使用,这就可以用多种条件编译选择;
3)#if也是必须要以#endif配合使用。
示例说明:
#include "stdio.h"
#include "stdlib.h"
#include "string.h"
typedef unsigned int uint32_t;
#define IFTEST1 0
#define IFTEST2 1
int main(void)
{
#if IFTEST1 //为假,不执行
printf("if : %d\n", IFTEST1);
#elif IFTEST2 //为真,执行
printf("if : %d!\n", IFTEST2);
#else //必须要加,不加执行不通过
printf("if : not true!\n");
#endif
system("pause");
return 0;
}
5、声明外部变量:extern
对于变量来说:
typedef signed char int8_t;
extern int8_t a; // 仅声明一个全局变量 a
int8_t a; // 定义一个全局变量 a
extern int8_t a =0 ; // 定义一个全局变量 a 并给初值。
int8_t a =0; // 定义一个全局变量 a, 并给初值,
第四个等于第三个,都是定义一个可以被外部使用的全局变量,并给初值。
但是定义只能出现在一处。也就是说,不管是int a;还是extern int a=0;还是int a=0;都只能出现一次,而那个extern int a可以出现很多次。
当你要引用一个全局变量的时候,你就必须要声明,extern int a; 这时候extern不能省略,因为省略了,就变成int a;这是一个定义,不是声明。注:extern int a; 中类型 int 可省略,即 extern a; 但其他类型则不能省略。
总结:
对变量而言,如果你想在本源文件(例如文件名A)中使用另一个源文件(例如文件名B)的变量,方法有2种:
(1)在A文件中必须用extern声明在B文件中定义的变量(当然是全局变量);
(2)在A文件中添加B文件对应的头文件(常用),前提是这个头文件包含B文件中的变量声明,也即在这个头文件中必须用extern声明该变量,否则,该变量又被定义一次。
如下图:1、.h中外部声明全局变量 2、.c中(包含对应.h)中定义全局变量
对函数而言,如果你想在本源文件(例如文件名A)中使用另一个源文件(例如文件名B)的函数,方法有2种:
(1)在A文件中用extern声明在B文件中定义的函数(其实,也可省略extern,只需在A文件中出现B文件定义函数原型即可);
(2)在A文件中添加B文件对应的头文件(常用),前提是这个头文件包含B文件中的函数原型,在头文件中函数可以不用加extern。
如下图:1、.h中外部声明函数 2、.c中(包含对应.h)中定义函数 3、.c中调用函数
6、extern "C"
extern "C"包含双重含义,从字面上可以知道,首先,被它修饰的目标是"extern"的;其次,被它修饰的目标代码是"C"的。
- 被extern "C"限定的函数或变量是extern类型的
extern是C/C++语言中表明函数和全局变量的作用范围的关键字,该关键字告诉编译器,其申明的函数和变量可以在本模块或其他模块中使用。
#ifndef _INCMODULE_H_ //为条件编译指令,防止该头文件被重复包含(或重定义)
#define _INCMODULE_H_ //对当前头文件进行定义#ifdef __cplusplus //告诉编译器,若是cpp文件,extern "C"{ } 中这部分代码按C语言的格式进行编译,而不是C++的。
extern "C"{
#endif/********字符数组定义*********/
static const char_t module_buf[100U]="2022-03-23 abcd"; //定义静态常量无符号类型字符数组
static const char_t module_buf[400]={’a’,’b’,’c’,’d’,’\0’}; //定义静态常量字符数组
#ifdef __linux__
#define _INTSIZEOF(n) ( (sizeof(n) + sizeof(int32_t) - 1) )
#endif
#define _crt_va_end(ap) ( ap = (va_list)0 )
/*…*/
#ifdef __cplusplus // 因为cpp文件默认定义了__cplusplus 该宏。
}#endif // 与 #ifdef __cplusplus 相对应
#endif /*与#ifndef 相对应 ,end of _INCMODULE_H_*/