C语言的预处理指令

时间:2022-06-24 12:57:52

  预处理指令是c语言支持的一种特殊指令,它们以#做开头,不以;做结尾。预处理指令在编译的第一个阶段被处理,所有预处理指令都是把程序变成另外的样子,宏和变量在计算机里的处理方式完全不同。
  gcc可以使用-E选项单独处理所有预处理指令。

1 define定义宏

“#define”是一个预处理指令,这个预处理指令用来定义宏,宏定义可以给数字起名称。
定义宏时不要使用=和; 宏名称中不应该有空格

可以在gcc命令行中使用-D选项定义宏
可以定义使用参数的宏,宏的参数都没有数据类型,也没有形参和实参的区别,宏的参数个数任意,宏的参数不一定代表一个数字。不要用自增或自减的计算结果作为宏的参数。
宏没有返回值变量
宏只能使用三目运算符完成复杂的计算

编写宏的时候应该在每个代表数字的参数以及整个计算结果外边都加上括号。

#include <stdio.h>

#define MAX(n1,n2) n1 > n2 ? n1 : n2
#define HEX(n) n >= '0' && n <= '9' ? n - '0' : n - 'a' + 10

int main() {
    printf("MAX(2, 8)是%d\n", MAX(2, 8));
    printf("HEX(\'7\')是%d\n", HEX('7'));
    printf("HEX(\'d\')是%d\n", HEX('d'));
    return 0;
}
#include <stdio.h>

#define PI 3.14f
#define SQUARE(n) ((n) * (n))
#define AREA(r) (PI * SQUARE(r))

int main() {
    int radius = 0;
    int num = 4;
    printf("请输入半径:");
    scanf("%d", &radius);
    printf("面积是%g\n", AREA(radius));
    printf("SQUARE(++num)是%d\n", SQUARE(++num));
    return 0;
}

2 #和##宏操作符

宏操作符#和##,都需要和宏的参数配合使用,这个参数通常不是用来表示数字的,#可以把宏的某个参数转化成字符串字面值。
“##”可以把一个代表名字的参数和其他内容合并得到一个新名字。

#include <stdio.h>

#define STR(n) #n
#define VAR(n) var_##n
int main() {
        int VAR(num) = 0;
        printf("STR(2 + 3 + 4)是%s\n", STR(2 + 3 + 4));
        return 0;
}

3 条件编译

条件编译可以只编译源程序的某一部分代码,条件编译是使用某些预处理指令实现的。
使用如下语句
“#ifdef/#ifndef ……#else ….. #endif”
可以根据某个宏是否被定义过把语句分成两组以实现条件编译。

#include <stdio.h>

int main() {
        int order = 0;
        printf("请点菜:");
        scanf("%d", &order);
#ifdef ZHAOBENSHAN
    if (!order) {
                printf("这个菜没有\n");
        }
        else {
                printf("这个真没有\n");
        }
#else
        printf("这个菜有\n");
#endif
        return 0;
}

“#if … #elif … #elif …#endif”
以上结构也是一种实现条件编译的方法,可以根据任何逻辑表达式区分,可以有多个分支。

#include <stdio.h>

int main() {
#if defined(FACTORY)
        printf("80%%\n");
#elif !defined(ELITE) && !defined(FACTORY)
        printf("100%%\n");
#else
        printf("120%%\n");
#endif
        return 0;
}

4 多文件程序编程

多文件程序编写的基本规则:
1、为每个.c源文件(除了含主函数的文件外)编写一个对应的头文件,头文件中包含.c源文件中所有函数的声明。
2、在每个.c源文件中包含对应的头文件。
3、如果某个.c源文件中使用到了某个.h头文件中声明的函数则也需要包含这个头文件。
头文件中应该使用条件编译避免多次编译。

在gcc命令中包含多个.c源文件名就可以编译多文件程序。

14add1.c

#include "14add1.h"
/*static*/ int result;
void add(int x, int y) {
    result = x + y;
}
14add1.h

#ifndef __14ADD1_H__
#define __14ADD1_H__
void add(int, int);
#endif //__14ADD1_H__
14add.c

#include <stdio.h>
#include "14add1.h"
extern int result;
int main() {
    add(4, 7);
    printf("add(4, 7)是%d\n", result);
    return 0;
}