打印
[其它应用]

C语言预处理命令,你知道多少?

[复制链接]
3074|43
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
我们在写C语言程序时,经常使用库函数之前,应该用#include引入对应的头文件。这种以#号开头的命令,就称为预处理命令。

但你对C语言的预处理了解多少呢?今天,我们就一起学习一下C语言中的预处理吧!

1. 预处理是什么?
预处理指令是以#号开头的代码行。#号必须是该行除了任何空白字符外的第一个字符。#后是指令关键字,在关键字和#号之间允许存在任意个数的空白字符。整行语句构成了一条预处理指令,该指令将在编译器进行编译之前对源代码做某些转换。

下面是部分预处理指令:



还有下列几种预处理宏(是双下划线):
__LINE__ 表示正在编译的文件的行号
__FILE__表示正在编译的文件的名字__DATE__表示编译时刻的日期字符串
__TIME__ 表示编译时刻的时间字符串
__STDC__ 判断该文件是不是定义成标准 C 程序
2. 预处理有什么用?
在集成开发环境中,编译,链接是同时完成的。其实,C语言编译器在对源代码编译之前,还需要进一步的处理:预编译。

所以完整的步骤是:预编译 -> 编译 -> 链接

预编译的主要作用如下:

1.将源文件中以”include”格式包含的文件复制到编译的源文件中。
2.用实际值替换用“#define”定义的字符串。
3.根据“#if”后面的条件决定需要编译的代码。
预处理是C语言的一个重要功能,由预处理程序完成。当对一个源文件进行编译时,系统将自动调用预处理程序对源程序中的预处理部分作处理,处理完毕自动进入对源程序的编译。

预处理的行为是由指令控制的。这些指令是由#字符开头的一些命令。

#define指令定义了一个宏---用来代表其他东西的一个命令,通常是某一个类型的常量。预处理会通过将宏的名字和它的定义存储在一起来响应#define指令。当这个宏在后面的程序中使用到时,预处理器”扩展”了宏,将宏替换为它所定义的值。

例如下面这行命令:

1

#define PI 3.141592654

#include指令告诉预处理器打开一个特定的文件,将它的内容作为正在编译的文件的一部分“包含”进来。

例如下面这行命令:

1

#include<stdio.h>

指示预处理器打开一个名字为stdio.h的文件,并将它的内容加到当前的程序中。

预处理器的输入是一个C语言程序,程序可能包含指令。预处理器会执行这些指令,并在处理过程中删除这些指令。预处理器的输出是另外一个程序:原程序的一个编辑后的版本,不再包含指令。预处理器的输出被直接交给编译器,编译器检查程序是否有错误,并经程序翻译为目标代码。

3. 三种预处理详解
1、宏定义指令

宏定义了一个代表特定内容的标识符。预处理过程会把源代码中出现的宏标识符替换成宏定义时的值。

宏最常见的用法是定义代表某个值的全局符号;而第二种用法是定义带参数的宏(宏函数),这样的宏可以象函数一样被调用,但它是在调用语句处展开宏,并用调用时的实际参数来代替定义中的形式参数。

#define指令:

#define预处理指令用来定义宏。该指令最简单的格式是:声明一个标识符,给出这个标识符代表的代码(比如像圆周率这样的数)。在后面的源代码中,我们就可以使用定义的宏取代要使用的代码,代码举例:

#define PI 3.141592654
使用宏的好处有两点:
一是使用方便。如下:

#define PI 3.1415926
PI显然比3.1415926写着方便。

二是定义的宏有了意义,可读性强。如例1,MAX_NUM,望文生意便知是最大数量的意思,比单纯使用10这个数字可读性要强的多。

三是容易修改。如例1,如果在程序中有几十次会使用到MAX_NUM,修改只需要在宏定义里面修改一次就可以,否则你会修改到崩溃。

2、条件编译指令

程序员可以通过定义不同的宏来决定编译程序对哪些代码进行处理。条件编译指令将决定哪些代码被编译,而哪些是不被编译的。可以根据表达式的值或者某个特定的宏是否被定义来确定编译条件。

#if/#endif/#else/#elif指令:

#if指令检测跟在制造另关键字后的常量表达式。如果表达式为真,则编译后面的代码,直到出现#else、#elif或#endif为止;否则就不编译。

#endif用于终止#if预处理指令。
#else指令用于某个#if指令之后,当前面的
#if指令的条件不为真时,就编译
#else后面的代码。
代码举例:

#define DEBUG       //此时#ifdef DEBUG为真
//#define DEBUG 0  //此时为假
int main()
{
   #ifdef DEBUG
      printf("Debugging\n");
   #else
      printf("Not debugging\n");
   #endif
   printf("Running\n");
   return 0;
}  
这样我们就可以实现debug功能,每次要输出调试信息前,只需要#ifdef DEBUG判断一次。不需要了就在文件开始定义#define DEBUG 0
#elif预处理指令综合了#else和#if指令的作用。

3、头文件包含指令

采用头文件的目的主要是为了使某些定义可以供多个不同的C源程序使用。因为在需要用到这些定义的C源程序中,只需加上一条#include语句即可,而不必再在此文件中将这些定义重复一遍。预编译程序将把头文件中的定义统统都加入到它所产生的输出文件中,以供编译程序对之进行处理。

#include预处理指令的作用是在指令处展开被包含的文件。包含可以是多重的,也就是说一个被包含的文件中还可以包含其他文件。标准C编译器至少支持八重嵌套包含。预处理过程不检查在转换单元中是否已经包含了某个文件并阻止对它的多次包含,这个的处理办法上面已经给出。

在程序中包含头文件有两种格式:

#include <my.h>
#include "my.h"
第一种方法是用尖括号把头文件括起来。这种格式告诉预处理程序在编译器自带的或外部库的头文件中搜索被包含的头文件。

第二种方法是用双引号把头文件括起来。这种格式告诉预处理程序在当前被编译的应用程序的源代码文件中搜索被包含的头文件,如果找不到,再搜索编译器自带的头文件。

采用两种不同包含格式的理由在于,编译器是安装在公共子目录下的,而被编译的应用程序是在它们自己的私有子目录下的。一个应用程序既包含编译器提供的公共头文件,也包含自定义的私有头文件。采用两种不同的包含格式使得编译器能够在很多头文件中区别出一组公共的头文件。

4. 小结
预编译程序所完成的基本上是对源程序的“替代”工作。经过此种替代,生成一个没有宏定义、没有条件编译指令、没有特殊符号的输出文件。这个文件的含义同没有经过预处理的源文件是相同的,但内容有所不同。下一步,此输出文件将作为编译程序的输出而被翻译成为机器指令。

使用特权

评论回复
沙发
mollylawrence| | 2023-12-4 08:59 | 只看该作者
#pragma:用于指示编译器特定的行为,具体的行为由编译器实现来决定。

使用特权

评论回复
板凳
belindagraham| | 2023-12-4 09:11 | 只看该作者
预处理命令在编程中起到重要作用,可以方便地实现代码重用、条件编译等功能,提高编程效率。

使用特权

评论回复
地板
cashrwood| | 2023-12-4 09:30 | 只看该作者
#pragma指令是一种预处理指令,用于实现一些特定的编译优化。例如,#pragma pack指令可以隐藏字节对齐问题,#pragma warning指令可以禁用某些警告信息。

使用特权

评论回复
5
albertaabbot| | 2023-12-4 09:53 | 只看该作者
#include指令是预编译指令,用于包含一个或多个源文件的内容。在预处理过程中,系统会将#include指令替换为所包含的文件内容。这样可以实现多个源文件的合并和重复利用,提高了代码的可读性和可维护性。

使用特权

评论回复
6
lzmm| | 2023-12-4 10:28 | 只看该作者
预处理指令以#号开头,#号后面的关键字和参数构成了一条预处理指令

使用特权

评论回复
7
qiufengsd| | 2023-12-4 10:41 | 只看该作者
#define指令用于定义一个宏。宏是一种简化代码的方式,可以通过一个符号来代替一串字符。在预处理过程中,系统会将#define指令替换为所定义的宏名和宏值。宏可以用于常量、变量和函数的定义。

使用特权

评论回复
8
jkl21| | 2023-12-4 11:02 | 只看该作者
宏定义又分为不带参数的宏定义和带参数的宏定义。不带参数的宏定义如:int b=6; int a[b]={1,2,3,4,5,6}; 这是错误的,因为b是变量。宏定义不会检测类型,这是缺点。

使用特权

评论回复
9
1988020566| | 2023-12-4 14:45 | 只看该作者
预处理命令可以帮助你更好地控制源代码的编译过程,并且提高代码的可读性和可维护性

使用特权

评论回复
10
nomomy| | 2023-12-4 15:03 | 只看该作者
#include:包含头文件。用于在源代码中引入头文件,头文件中包含编译器相关的定义、宏、函数声明等。
#define:定义宏。用于定义一个宏,供后续代码调用。
#undef:删除宏。用于删除之前已经定义的宏。
#if、#else、#elif、#endif:条件编译。用于根据条件编译代码块。
#ifdef、#ifndef:带参数的宏定义。与#define类似,但带参数的宏定义只在满足特定条件时才会被定义。
#line:设置编译行号。用于改变编译器生成的代码中的行号,便于调试和问题定位。
#error:错误处理。用于在编译时产生错误信息,用于代码检查。
#pragma:编译器指令。用于向编译器传递一些编译选项或指令,以改变编译行为。
#warning:编译警告。用于在编译时产生警告信息,提醒开发者注意某些问题。
#version:编译器版本控制。用于指定编译器版本,以便程序在不同编译器版本下保持一致性。

使用特权

评论回复
11
biechedan| | 2023-12-4 15:37 | 只看该作者
C语言预处理命令是在编译阶段之前进行的一些处理,包括宏定义、条件编译、文件包含等。

使用特权

评论回复
12
mmbs| | 2023-12-4 16:15 | 只看该作者
C语言预处理命令是在编译之前由预处理器执行的一系列指令。它们用于控制源代码的编译过程,并且不会影响到程序的运行。

使用特权

评论回复
13
jonas222| | 2023-12-4 16:28 | 只看该作者
文件包含指令(#include)用于将头文件的内容插入到源程序中,这对于实现模块化编程和函数重用非常重要。

使用特权

评论回复
14
belindagraham| | 2023-12-5 10:38 | 只看该作者
预处理指令不是C语言的组成部分,而是在编译之前对源代码进行处理。经过预处理后,程序将不再包括预处理命令,只剩下编译器可以处理的源代码。

使用特权

评论回复
15
uptown| | 2023-12-5 12:58 | 只看该作者
#line 用于修改编译器的行号指示,即在源代码中改变编译器对行号的处理方式。

使用特权

评论回复
16
geraldbetty| | 2023-12-5 14:46 | 只看该作者
条件编译指令(例如#if、#ifdef、#ifndef、#else、#elif等)允许程序员在特定条件下决定哪些代码会被编译和执行。

使用特权

评论回复
17
AdaMaYun| | 2023-12-5 15:18 | 只看该作者
预处理指令是以#号开头的代码行。

使用特权

评论回复
18
jtracy3| | 2023-12-5 15:34 | 只看该作者
#ifndef指令和#endif指令用于保护代码段。它们可以保护一些不希望被其他文件包含的代码段。当预处理器遇到#ifndef指令时,它会查找其后的代码段,直到找到#endif指令或者代码段结束。如果代码段没有被其他文件包含,则该代码段将被保护,不会被其他文件包含或者重复包含。

使用特权

评论回复
19
benjaminka| | 2023-12-5 16:19 | 只看该作者
#if指令和#elif指令用于条件编译。它们可以判断程序执行时的条件,并根据条件进行不同的编译。#if指令和#elif指令的语法格式如下:

#if 条件
代码块
#elif 条件
代码块
#else
代码块
#endif

使用特权

评论回复
20
mollylawrence| | 2023-12-5 17:02 | 只看该作者
一些常见的C语言预处理命令:
#include:用于引入一个源代码文件,将文件内容复制到当前文件中。
#define:用于定义一个宏,可以用实际值替换。
#undef:用于取消已定义的宏。
#if:用于根据给定条件判断是否编译后续代码。
#ifdef:用于判断某个宏是否已经定义,如果已定义,则跳过后续代码。
#ifndef:用于判断某个宏是否未定义,如果未定义,则编译后续代码。
#elif:用于条件编译的嵌套。
#else:用于条件编译的else分支。
#endif:用于结束条件编译。

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

1884

主题

6474

帖子

8

粉丝