C语言基础06:预编译指令

一、C语言的执行流程

(一)编译

    编译器将源代码转换成机器语言的过程。在编译过程中,会找出并报告错误,最后形成源文件(在Windows下是扩展名为.obj的文件,在Linux或者UNIX环境中是.o)。
    编译过程包括两个阶段。第一个阶段称为预处理阶段,在此期间会修改或添加代码,第二个阶段是生成对象代码的实际编译过程。

(二)链接

    将源文件(.obj或者.o文件)和C函数库连接合并,形成最终的可执行文件(Windows下扩展名为.exe,UNIX环境下没有扩展名,但它是一个可执行的文件类型)。

(三)执行

    在这个阶段,计算机最终会精确地执行指令。

C语言基础06:预编译指令_第1张图片
图1-1 创建和执行程序

二、预编译(预处理):为编译工作做准备工作,完成代码文本的替换工作

(一)预处理指令

符号#表示这是一个预处理指令(preprocessing directive),告诉编译器在编译源代码之前,要先执行一些操作。

1.include指令

#include ,这是将stdio.h文件的内容包含进来,stdio文件称为头文件

2.define指令(也叫宏定义、宏替换或者预编译指令)

1.定义标示

  • #ifdef __cplusplus:标识支持C++语法
  • #pragma once:防止文件重复引入:
    C语言基础06:预编译指令_第2张图片
    图2-1 文件重复引用

    如图所示.c源文件引用了A.h的头文件,A.h又和B.h存在相互引用的关系,那么A和B两个头文件就会造成重复引入的错误。
    C语言基础06:预编译指令_第3张图片
    图2-2 文件重复引用错误

解决办法是,在A.hB.h头文件的开头使用#pragma once,它表示该头文件只被包含一次,编译器会自动处理好循环包含的问题。

//A.h
#pragma once
#include "B.h"

void printfA();
//B.h
#pragma once
#include "A.h"

void printfB();

2.定义常数(便于修改与阅读)

  • #define MAX 200

3.定义“宏函数”

  • 示例代码如下
#include 
#include 

void com_gjg_jni_read(){
    printf("read\n");
}

void com_gjg_jni_write(){
    printf("write\n");
}

//##表示要替换的部分
#define jni(name) com_gjg_jni_##name();

void main(){
    //根据传入的name值,决定调用哪个函数
    jni(read);
    jni(write);
    getchar();
}
C语言基础06:预编译指令_第4张图片
图2-3 宏函数
  • 示例代码如下
#include 
#include 

//__VA_ARGS__表示可变参数
#define LOG(FORMAT,...) printf(##FORMAT,__VA_ARGS__);
#define LOG_I(FORMAT,...) printf("INFO:"); LOG(##FORMAT,__VA_ARGS__);
#define LOG_E(FORMAT,...) printf("ERROR:"); LOG(##FORMAT,__VA_ARGS__);

void main(){
    LOG_I("%s,%d\n", "我是详细信息",12);
    LOG_E("%s,%d\n", "我是错误信息",24);
    getchar();
}
C语言基础06:预编译指令_第5张图片
图2-4 宏函数

(二)定义自己的头文件

    可以定义自己的头文件,通常扩展名是.h,头文件名称通常用小写,可以使用操作系统允许的任何文件名。头文件不能包含实现代码,即可执行代码。可以在头文件中放置函数原型、struct类型定义、符号定义、extern语句和typedefs。一个常用的技巧是创建一个头文件,它含有程序中所有函数的原型以及类型声明。

END

你可能感兴趣的:(C语言基础06:预编译指令)