精华内容
下载资源
问答
  • c语言编译预处理命令

    2020-04-07 11:04:50
    c语言用#define 来声明一个宏,宏可以带参数,如: #define PI 3.14 //定义一个宏PI表示3.14 #define CIRCLE_AREA ((x)*(x)*(PI)) //定义宏计算圆的面积 如果一行写不下,可以加入反斜杠’\'表示下一行也是宏的声明,...

    一. 宏

    c语言用#define 来声明一个宏,宏可以带参数,如:

    #define PI 3.14 //定义一个宏PI表示3.14
    #define CIRCLE_AREA ((x)*(x)*(PI)) //定义宏计算圆的面积
    

    如果一行写不下,可以加入反斜杠’\'表示下一行也是宏的声明,下面代码等价:

    #define NAME  "xiaohaha"
    
    #define NAME \
    "xiaohaha"
    

    定义的宏可以被#undef撤销

    二.条件编译

    每个#if结构都以#endif结束
    #ifdef HONG#if defined(HONG)等价
    #ifndef#if !defined(HONG)等价
    注意前者没有括号,后者需要将宏用括号括起来

    调试程序时,我们经常需要输出一些变量的值,可以用:

    #ifdef DEBUG
    	printf("Variable x = %d\n",x);
    #endif
    

    只有前面定义过DEBUG,该语句才会被编译执行

    三.#和##运算符

    # 可以将标记转换成用引号引起的字符串,如:

    #define HELLO(x) printf("Hello,"#x"\n")
    //HELLO(xiaohaha) equals printf("Hello,""xiaohaha""\n")
    

    ==##==将两个标记拼接在一起,如:

    #define TOKENCONCAT(x,y)  x##y
    

    当程序中出现TOKENCONCAT(O,K)时,将会被OK替换

    四.断言

    断言assert()测试一个表达式的值,如果表达式为假,则打印出错信息并调用abort函数结束程序
    需要#include<assert.h>
    通过定义NDEBUG可以忽略其后所有断言
    #define NDEBUG必须放在#include<assert.h>之前

    五.头文件

    以下定义头文件的模板可以有效避免多次include同一个头文件:

    #ifndef _COORDIN_H
    #define _COORDIN_H
    ... // 头文件的内容
    #endif
    
    展开全文
  • 单项选择题 在宏定义#define A) 单精度数 符串 以下叙述中正确的是 A)预处理命令行必须位于源文件的开头 多条预处理命令 C)宏名必须用大写字母表示 时间 C语言编译系统对宏命令的处理( A) B) C) D) 3. 4. 5. 中宏...
  • C语言编译预处理

    千次阅读 2008-03-28 17:13:00
    预处理C程序的源代码中可包括各种编译指令,这些指令称为预处理命令。虽然它们实际上不是C语言的一部分,但却扩展了C程序设计的环境。本节将介绍如何应用预处理程序和注释简化程序开发过程,并提高程序的可读性。...

    预处理

    C程序的源代码中可包括各种编译指令,这些指令称为预处理命令。虽然它们实际上不是C语言的一部分,但却扩展了C程序设计的环境。本节将介绍如何应用预处理程序和注释简化程序开发过程,并提高程序的可读性。

    4.7.1C语言的预处理程序

    ANSI标准定义的C语言预处理程序包括下列命令:

    #define

    #error

    #include

    #if

    #else

    #elif

    #endif

    #ifdef

    #ifndef

    #undef

    #line

    #pragma

    非常明显,所有预处理命令均以符号#开头,下面分别加以介绍。

    4.7.2#define

    命令#define定义了一个标识符及一个串。在源程序中每次遇到该标识符时,均以定义的串代换它。ANSI标准将标识符定义为宏名,将替换过程称为宏替换。命令的一般形式为:

    #define identifier string

    注意,该语句没有分号。在标识符和串之间可以有任意个空格,串一旦开始,仅由一新行结束。

    例如,如希望TURE取值1,FALSE取值0,可说明两个宏#define

    #define TURE 1

    #define FALSE 0

    这使得在源程序中每次遇到TURE或FALSE就用0或1代替。

    例如,在屏幕上打印“012”:

    printf("%d%d%d",FALSE,TRUE,TRUE+1);

    宏名定义后,即可成为其它宏名定义中的一部分。例如,下面代码定义了ONE、TWO及THREE的值。

    #define ONE 1

    #define TWO ONE+ONE

    #define THREE ONE+TWO

    懂得宏替换仅仅是以串代替标识符这点很重要。因此,如果希望定义一个标准错误信息,可编写如下代码:

    #defineE_MS"standard error on input/n"

    printf(E_MS);

    编译程序遇到标识符E_MS时,就用“standard error on input/n”替换。对于编译程序,printf()语句实际是如下形式:

    printf("standard error on input/n;")

    如果在串中含有标识符,则不进行替换。例如:

    #define XYZ this is a test

    .

    .

    .

    printf("XYZ");

    该段不打印"this is a test"而打印"XYZ"。

    如果串长于一行,可以在该行末尾用一反斜杠续行,例如:

    #defineLONG_STRING"this is a very long/

    string that is used as an example"

    C语言程序普遍使用大写字母定义标识符。这种约定可使人读程序时很快发现哪里有宏替换。最好是将所有的#define放到文件的开始处或独立的文件中(用#include访问),而不是将它们分散到整个程序中。

    宏代换的最一般用途是定义常量的名字和程序中的“游戏数”。例如,某一程序定义了一个数组,而它的几个子程序要访问该数组,不应直接以常量定数组大小,最好是用名字定义之(需改变数组大小时)。

    #define MAX_SIZE100

    float balance [MAX_SIZE;]

    #define命令的另一个有用特性是,宏名可以取参量。每次遇到宏名时,与之相连的形参均由程序中的实参代替。例如:

    当编译该程序时,由MIN(a,b)定义的表达式被替换,x和y用作操作数,即printf()语句被代换后取如下形式:

    printf("the minimum is:%,d"(x<y)?x:y);

    用宏代换代替实在的函数的一大好处是宏替换增加了代码的速度,因为不存在函数调用的开销。但增加速度也有代价:由于重复编码而增加了程序长度。

    4.7.3#error

    处理器命令#error强迫编译程序停止编译,主要用于程序调试。

    #if(ROW<2)     //超出范编译报错
          #error  ROW of num is litter
          #endif

    4.7.4#include

    命令#include使编译程序将另一源文件嵌入带有#include的源文件,被读入的源文件必须用双引号或尖括号括起来。例如:

    #include"stdio.h"

    #include<stdio.h>

    这两行代码均使用C编译程序读入并编译用于处理磁盘文件库的子程序。

    将文件嵌入#include命令中的文件内是可行的,这种方式称为嵌套的嵌入文件,嵌套层次依赖于具体实现。

    如果显式路径名为文件标识符的一部分,则仅在哪些子目录中搜索被嵌入文件。否则,如果文件名用双引号括起来,则首先检索当前工作目录。如果未发现文件,则在命令行中说明的所有目录中搜索。如果仍未发现文件,则搜索实现时定义的标准目录。

    如果没有显式路径名且文件名被尖括号括起来,则首先在编译命令行中的目录内检索。

    如果文件没找到,则检索标准目录,不检索当前工作目录。

    4.7.5条件编译命令

    有几个命令可对程序源代码的各部分有选择地进行编译,该过程称为条件编译。商业软件公司广泛应用条件编译来提供和维护某一程序的许多顾客版本。

    1.#if、#else,#elif及#endif

    #if的一般含义是如果#if后面的常量表达式为true,则编译它与#endif之间的代码,否则跳过这些代码。命令#endif标识一个#if块的结束,参见例4-13。

    #ifconstant-expression

    statement sequence

    #endif

    由于MAX大于99,以上程序在屏幕上显示一串消息。该例说明了一个重点:跟在#if后面的表达式在编译时求值,因此它必须仅含常量及已定义过的标识符,不可使用变量。表达式不许含有操作符sizeof。

    #else命令的功能有点象C语言中的else;#else建立另一选择(在#if失败的情况下)。因而上面的例子可扩充,参见例4-14。

    在此例中,因为M A X小于9 9,所以,不编译#if块,而是编译# else块,因此,屏幕上显

    示"compiled for small array"这一消息。

    注意,# else 既是# if 块又是#else 块头。这是因为任何#if 仅有一个#endif。

    #elif命令意义与ELSE IF 相同,它形成一个if else-if阶梯状语句,可进行多种编译选择。

    #elif 后跟一个常量表达式。如果表达式为t r u e,则编译其后的代码块,不对其它#elif表达式进

    行测试。否则,顺序测试下一块。

    #if expression

    statement sequence

    #elif expression1

    statement sequence

    #elif expression2

    statement sequence

    #elif expression3

    statement sequence

    #elif expression4

    #elif expression3N

    statement sequence

    #endif

    例如:下面程序利用ACTI Ve_ COUNTRY定义货币符号。

    #define US 0

    #define ENGLAND1

    #define FRANCE 2

    # define ACTIVE_COUNTRY US

    #if ACTIVE_COUNTRY = = US

    char currency[ ]="dollar; "

    #elif ACTIVE_COUNTRY= =ENGLAND

    char currency[ ]="pound; "

    #else

    char currency[ ]="franc;"

    #endif

    #if与#elif命令可能一直嵌套到实现规定的权限,其中#endif、#else或#elif与最近#if或#elif关联。例如,下面程序是完全有效的。

    #if MAX>100

    #if SERIAL_VERSION

    int port=198;

    #elif

    int port=200;

    #elif

    #else

    char out_buffer[100];

    #endif

    2. # ifdef 和# ifndef

    条件编译的另一种方法是用#ifdef与#ifndef命令,它们分别表示“如果有定义”及“如果无定义”。

    # ifdef的一般形式是:

    # ifdef macroname

    statement sequence

    #endif

    如果宏名在前面# def i n e语句中已定义过,则该语句后的代码块被编译。

    #ifndef的一般形式是:

    #ifndef macroname

    statement sequence

    #endif

    如果宏名在#define 语句中无定义,则编译该代码块。

    #ifdel 与#ifndef可以用于#else 语句中,但#elif 不行。参见4 - 1 5。

    上述代码打印“ Hi Ted ”及“ RALPH not defined”。如果T E D没有定义,则显示“ H i a n y o n e”,后面是“ RALPH not defined”。

    可以像嵌套#if 那样将#ifdef 与#ifndef 嵌套至任意深度。

    4.7.6 #undef

    命令#undef 取消其后那个前面已定义过有宏名定义。一般形式为:

    #undef macroname

    例如:

    # define LEN 100

    #difine WIDTH 100

    char array[LEN][WIDTH];

    # undef LEN

    # undef WIDTH

    / *at this point both LEN and WIDTH are undefined * /

    直到遇到#undef 语句之前, L E N与W I D T H均有定义。

    # undef 的主要目的是将宏名局限在仅需要它们的代码段中。

    4.7.7 #line

    命令# line改变_LINE_ 与_ F I L E _的内容,它们是在编译程序中预先定义的标识符。

    命令的基本形式如下:

    # line number["filename"]

    其中的数字为任何正整数,可选的文件名为任意有效文件标识符。行号为源程序中当前行号,文件名为源文件的名字。命令# line主要用于调试及其它特殊应用。

    例如,下面说明行计数从1 0 0开始;printf( ) 语句显示数1 0 2,因为它是语句#line 100后的第3行。

    #line 100 /* 初始化行计数器* /

    main ( ) /* 行号100 */

    { /* 行号101 */

    p r i n t f ( " % d / n " ,_ line _ ) ; /* 行号102 */

    }

    4.7.8 #pragma

    命令#pragma 为实现时定义的命令,它允许向编译程序传送各种指令。例如,编译程序可能有一种选择,它支持对程序执行的跟踪。可用# p r a g m a语句指定一个跟踪选择。

    4.7.9 预定义的宏名

    A N S I标准说明了五个预定义的宏名。它们是:

    _ line _

    _ F I L E _

    _ D A T E _

    _ T I M E _

    _ S T D C _

    如果编译不是标准的,则可能仅支持以上宏名中的几个,或根本不支持。记住编译程序也许还提供其它预定义的宏名。

    _ line _及_ F I L E _宏指令在有关# line的部分中已讨论,这里讨论其余的宏名。

    _ D AT E _宏指令含有形式为月/日/年的串,表示源文件被翻译到代码时的日期。

    源代码翻译到目标代码的时间作为串包含在_ T I M E _中。串形式为时:分:秒。

    如果实现是标准的,则宏_ S T D C _含有十进制常量1。如果它含有任何其它数,则实现是非标准的。

    注意:宏名的书写由标识符与两边各二条下划线构成。

    4.7.10 注释

    C语言中,所有的注释由字符/ *开始,以* /结束。在星号及斜杠之间不允许有空格。编译程序忽略注释开始符到注释结束符间的任何文本。例如,下面程序在屏幕上只打印

    “h e l l o”。

    main ()

    {

    p r i n t f ( "hello" ) ;

    /*printf ("This is a sample to print hell;o"*/)

    }

    注释可出现在程序的任何位置,但它不能出现在关键字或标识符中间。

    即,注释x=10+ /*add the numbers */ 5;是有效的,但swi/* this will not work */tch(c){...

    是不正确的,因为C的关键字不能含有注释。通常也不希望表达式中间出现注释,因为这会使

    意义含混不清。

    注释不可嵌套,即一个注释内不可含有另一个注释。例如,下面代码段在编译时出错:

    /*this is an outer comment

    x = y / a ;

    /*this is an inner comment -and causes an error */

    * /

    当需要解释程序的行为时,注释应简明扼要。除了最简单和最直观的函数外,都应有注释,在函数开始处说明其功能,如何调用以及返回何处。

    http://tony.hehui.blog.163.com/blog/static/422087322007931101226359/转载地址<br />c编译预处理 

     
    展开全文
  • 编译预处理是指C语言对源程序在正常编译(包括语法分析,词法分析,代码生成和代码优化)之前先执行源程序中的预处理命令。预处理后,源程序再被正常编译,然后得到目标文件(obj文件)。 预处理阶段有四件事完成...

    编译预处理是指C语言对源程序在正常编译(包括语法分析,词法分析,代码生成和代码优化)之前先执行源程序中的预处理命令。预处理后,源程序再被正常编译,然后得到目标文件(obj文件)。
    这里写图片描述
    预处理阶段有四件事完成:
    头文件的包含
    注释的删除
    define标识符的替换与删除
    宏替换

    define
    #define 定义标识符
    #define 标识符 字符串
    这里写图片描述
    #define 宏定义
    #define 允许带参数,在宏定义中的参数叫形参,在宏调用中的参数叫实参。
    这里写图片描述

    宏定义与函数有类似之处,但在本质上是不同的。
    这里写图片描述

    条件编译
    这里写图片描述

    条件编译命令的优点:
    条件编译命令可以给程序调试带来方便。
    条件编译命令可以使一个源程序生成不同的目标代码。
    使用条件编译命令替代if语句会减少目标代码的长度。

    预定义符号
    这里写图片描述

    展开全文
  • C语言的程序中可包括各种以符号#开头的编译指令,这些指令称为预处理命令预处理命令属于C语言编译器,而不是C语言的组成部分。通过预处理命令可扩展C语言程序设计的环境。 一.预处理的工作方式 1.1.预处理的...

    引用地址:

    https://www.cnblogs.com/haore147/p/3646962.html

    在C语言的程序中可包括各种以符号#开头的编译指令,这些指令称为预处理命令。预处理命令属于C语言编译器,而不是C语言的组成部分。通过预处理命令可扩展C语言程序设计的环境。

    一.预处理的工作方式
     
    1.1.预处理的功能
     
      在集成开发环境中,编译,链接是同时完成的。其实,C语言编译器在对源代码编译之前,还需要进一步的处理:预编译。

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

      预编译的主要作用如下:

    1

    2

    3

    1.将源文件中以”include”格式包含的文件复制到编译的源文件中。

    2.用实际值替换用“#define”定义的字符串。

    3.根据“#if”后面的条件决定需要编译的代码。

     

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


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

    1

    #define PI 3.141592654


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

    1

    #include<stdio.h>

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

     

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


    二.预处理指令
     
     2.1.预处理指令
     
    大多数预处理器指令属于下面3种类型:

    1

    2

    3

    宏定义:#define 指令定义一个宏,#undef指令删除一个宏定义。

    文件包含:#include指令导致一个指定文件的内容被包含到程序中。

    条件编译:#if,#ifdef,#ifndef,#elif,#else和#endif指令可以根据编译器可以测试的条件来将一段文本包含到程序中或排除在程序之外。

    剩下的#error,#line和#pragma指令更特殊的指令,较少用到。

     

    2.2.指令规则
     

    1

    2

    3

    4

    5

    指令都是以#开始。#符号不需要在一行的行首,只要她之前有空白字符就行。在#后是指令名,接着是指令所需要的其他信息。

    在指令的符号之间可以插入任意数量的空格或横向制表符。

    指令总是第一个换行符处结束,除非明确地指明要继续。

    指令可以出现在程序中任何地方。我们通常将#define和#include指令放在文件的开始,其他指令则放在后面,甚至在函数定义的中间。

    注释可以与指令放在同一行。

     


    三.宏定义命令----#define   
          
      使用#define命令并不是真正的定义符号常量,而是定义一个可以替换的宏。被定义为宏的标示符称为“宏名”。在编译预处理过程时,对程序中所有出现的“宏名”,都用宏定义中的字符串去代换,这称为“宏代换”或“宏展开”。

    在C语言中,宏分为有参数和无参数两种。
     

    3.1.无参数的宏

     

    其定义格式如下:

    1

    #define 宏名  字符串

    在以上宏定义语句中,各部分的含义如下:

    1

    2

    3

    4

    #:表示这是一条预处理命令(凡是以“#”开始的均为预处理命令)。

    define:关键字“define”为宏定义命令。

    宏名:是一个标示符,必须符合C语言标示符的规定,一般以大写字母标示宏名。

    字符串:可以是常数,表达式,格式串等。在前面使用的符号常量的定义就是一个无参数宏定义。

    Notice:预处理命令语句后面一般不会添加分号,如果在#define最后有分号,在宏替换时分号也将替换到源代码中去。在宏名和字符串之间可以有任意个空格。

    1

    #define PI 3.14

      

    在使用宏定义时,还需要注意以下几点:

    1

    2

    3

    4

    5

    6

    7

    8

    9

    宏定义是宏名来表示一个字符串,在宏展开时又以该字符串取代宏名。这只是一种简单的代换,字符串中可以含任何字符,可以是常数,也可以是表达式,预处理程序对它不作任何检查。如有错误,只能在编译已被宏展开后的源程序时发现。

     

    宏定义必须写在函数之外,其作用域为宏定义命令起到源程序结束。

     

    宏名在源程序中若用引号括起来,则预处理程序不对其作宏替换。

     

    宏定义允许嵌套,在宏定义的字符串中可以使用已经定义的宏名。在宏展开时由预处理程序层层替换。

     

    习惯上宏名可用大写字母表示,以方便与变量区别。但也允许用小写字母。

     

    3.2带参数的宏
     

    1

    #define命令定义宏时,还可以为宏设置参数。与函数中的参数类似,在宏定于中的参数为形式参数,在宏调用中的参数称为实际参数。对带参数的宏,在调用中,不仅要宏展开,还要用实参去代换形参。

    带参宏定义的一般形式为:

    1

    #define 宏名(形参表) 字符串  


    在定义带参数的宏时,宏名和形参表之间不能有空格出现,否则,就将宏定义成为无参数形式,而导致程序出错。

    1

    #define ABS(x)  (x)<0?-(x):(x)

     以上的宏定义中,如果x的值小于0,则使用一元运算符(-)对其取负,得到正数。

     

      带参的宏和带参的函数相似,但其本质是不同的。使用带参宏时,在预处理时将程序源代码替换到相应的位置,编译时得到完整的目标代码,而不进行函数调用,因此程序执行效率要高些。而函数调用只需要编译一次函数,代码量较少,一般情况下,对于简单的功能,可使用宏替换的形式来使用。
     

    3.3.预处理操作符#和##
     
    3.3.1.操作符#
     
       在使用#define定义宏时,可使用操作符#在字符串中输出实参。Eg:

    1

    #define AREA(x,y) printf(“长为“#x”,宽为“#y”的长方形的面积:%d\n”,(x)*(y));

     

    3.3.2.操作符##
     
    与操作符#类似,操作符##也可用在带参宏中替换部分内容。该操作符将宏中的两个部分连接成一个内容。例如,定义如下宏:

    1

    #define VAR(n)   v##n 

     

    当使用一下方式引用宏:

    1

    VAR(1) 

    预处理时,将得到以下形式:

    1

     

     

    如果使用以下宏定义:

    1

    #define FUNC(n)  oper##n  

    当实参为1时,预处理后得到一下形式:

    1

    oper1

     

    四.文件包含------include
     
      当一个C语言程序由多个文件模块组成时,主模块中一般包含main函数和一些当前程序专用的函数。程序从main函数开始执行,在执行过程中,可调用当前文件中的函数,也可调用其他文件模块中的函数。
        

      如果在模块中要调用其他文件模块中的函数,首先必须在主模块中声明该函数原型。一般都是采用文件包含的方法,包含其他文件模块的头文件。


      文件包含中指定的文件名即可以用引号括起来,也可以用尖括号括起来,格式如下:

    1

    2

    3

    #include< 文件名>

    #include“文件名”

     

      如果使用尖括号<>括起文件名,则编译程序将到C语言开发环境中设置好的 include文件中去找指定的文件。

      因为C语言的标准头文件都存放在include文件夹中,所以一般对标准头文件采用尖括号;对编程自己编写的文件,则使用双引号。

      如果自己编写的文件不是存放在当前工作文件夹,可以在#include命令后面加在路径。
       

      #include命令的作用是把指定的文件模块内容插入到#include所在的位置,当程序编译链接时,系统会把所有#include指定的文件链接生成可执行代码。文件包含必须以#开头,表示这是编译预处理命令,行尾不能用分号结束。
      

      #include所包含的文件,其扩展名可以是“.c”,表示包含普通C语言源程序。也可以是 “.h”,表示C语言程序的头文件。C语言系统中大量的定义与声明是以头文件形式提供的。 “.h”是接口文件,如果想理解C语言接口的写法,有必要琢磨一下 “.h”。

      

      通过#define包含进来的文件模块中还可以再包含其他文件,这种用法称为嵌套包含。嵌套的层数与具体C语言系统有关,但是一般可以嵌套8层以上。

     

    五.条件编译
     

      预处理器还提供了条件编译功能。在预处理时,按照不同的条件去编译程序的不同部分,从而得到不同的目标代码。

      使用条件编译,可方便地处理程序的调试版本和正式版本,也可使用条件编译使程序的移植更方便。

    5.1使用#if


    与C语言的条件分支语句类似,在预处理时,也可以使用分支,根据不同的情况编译不同的源代码段。


    #if 的使用格式如下:

    1

    2

    3

    4

    5

    #if 常量表达式

       程序段

    #else

      程序段

    #endif

     

    该条件编译命令的执行过程为:若常量表达式的值为真(非0),则对程序段1进行编译,否则对程序段2进行编译。因此可以使程序在不同条件下完成不同的功能。

    举个例子:

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    12

    13

    14

    15

    16

    17

    18

    19

    20

    21

    22

    23

    24

    25

    26

    27

    #define DEBUG 1

     

    int main()

     

    {

     

       int i,j;

       char ch[26];

     

       for(i='a';j=0;i<='z';i++,j++)

       {

           ch[j]=i;

     

           #if DEBUG

     

              printf("ch[%d]=%c\n",j,ch[j]);

     

           #endif

     

       }

     

       for(j=0;j<26;j++)

       {

           printf("%c",ch[j]);

       }

       return 0;

    }

      

    #if预编译命令还可使用多分支语句格式,具体格式如下:

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    12

    13

    14

    15

    16

    17

    18

    19

    #if 常量表达式 1

     

        程序段 1

     

    #elif 常量表达式 2

     

        程序段 2

     

    … …

     

    #elif 常量表达式 n

     

        程序段 n

     

    #else

     

        程序段 m

     

    #endif

     

    关键字#elif与多分支if语句中的else if类似。
    举个例子

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    12

    13

    14

    15

    #define os win

     

    #if os=win

     

        #include"win.h"

     

    #elif os=linux

     

        #include"linux.h"

     

    #elif os=mac

     

        #include"mac.h"

     

    #endif

     

    #if和#elif还可以进行嵌套,C89标准中,嵌套深度可以到达8层,而C99允许嵌套达到63层。在嵌套时,每个#endif,#else或#elif与最近的#if或#elif配对。
    Eg:

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    12

    13

    14

    15

    16

    17

    18

    19

    20

    21

    22

    23

    24

    25

    26

    27

    28

    29

    30

    31

    32

    33

    34

    35

    36

    37

    38

    39

    40

    41

    42

    43

    44

    45

    46

    47

    48

    49

    50

    51

    52

    53

    54

    55

    56

    57

    58

    59

    60

    61

    62

    63

    64

    65

    66

    67

    68

    69

    70

    71

    72

    73

    74

    75

    #define MAX 100

    #define OLD -1

     

    int main()

    {

    int i;

     

    #if MAX>50

     

        #if OLD>3

     

        {

     

            i=1;

     

        {

     

        #elif OLD>0

     

        {

     

            i=2;

     

        }

     

        #else

     

        {

     

            i=3;

     

        }

     

        #endif

     

    }

     

    #else

     

    {

     

        #if OLD>3

     

        {

     

            i=4;

     

        }

     

        #elif OLD>4

     

        {

     

            i=5;

     

        }

     

        #else

     

        {

     

            i=6;

     

        }

     

        #endif

     

    }

     

    #endif

     

    return 0;

     

    }

     

    5.2使用#ifdef和#ifndef
     
    在上面的#if条件编译命令中,需要判断符号常量定义的具体值。在很多情况下,其实不需要判断符号常量的值,只需要判断是否定义了该符号常量。这时,可不使用#if命令,而使用另外一个预编译命令———#ifdef.

    1

    2

    3

    4

    5

    6

    7

    8

    9

    #ifdef命令的使用格式如下:

    #ifdef 标识符

    程序段 1

     

    #else

     

        程序段 2

     

    #endif

    其意义是,如果#ifdef后面的标识符已被定义过,则对“程序段1”进行编译;如果没有定义标识符,则编译“程序段2”。一般不使用#else及后面的“程序2”。

    而#ifndef的意义与#ifdef相反,其格式如下:

    1

    2

    3

    4

    5

    6

    7

    8

    #ifndef 标识符

        程序段 1

     

    #else

     

        程序段 2

     

    #endif

    其意义是:如果未定义标识符,则编译“程序段1”;否则编译“程序段2”。

     


    5.3使用#defined和#undef
     
    与#ifdef类似的,可以在#if命令中使用define来判断是否已定义指定的标识符。例如:

    1

    2

    3

    4

    #if defined 标识符

    程序段 1 

     

    #endif

     

    与下面的标示方式意义相同。

    1

    2

    3

    4

    #ifdef 标识符

        程序段 1

     

    #endif

     

    也可使用逻辑运算符,对defined取反。例如:

    1

    2

    3

    4

    #if ! define 标识符

        程序段 1

     

    #endif

     

    与下面的标示方式意义相同。

    1

    2

    3

    4

    #ifndef 标识符

        程序段 1

     

    #endif

     

    在#ifdef和#ifndef命令后面的标识符是使用#define进行定义的。在程序中,还可以使用#undef取消对标识符的定义,其形式为:

    1

    #undef 标识符  


    举个例子:

    1

    2

    3

    4

    5

    #define MAX 100

     

    ……

     

    #undef MAX

     

    在以上代码中,首先使用#define定义标识符MAX,经过一段程序代码后,又可以使用#undef取消已定义的标识符。使用#undef命令后,再使用#ifdef max,将不会编译后的源代码,因为此时标识符MAX已经被取消定义了。

     

    六.其他预处理命令
     
     6.1.预定义的宏名
     
           ANSI C标准预定义了五个宏名,每个宏名的前后均有两个下画线,避免与程序员定义相同的宏名(一般都不会定义前后有两个下划线的宏)。这5个宏名如下:

    1

    2

    3

    4

    5

    __DATE__:当前源程序的创建日期。

     __FILE__:当前源程序的文件名称(包括盘符和路径)。

    __LINE__:当前被编译代码的行号。

    __STDC__:返回编译器是否位标准C,若其值为1表示符合标准C,否则不是标准C.

    __TIME__:当前源程序的创建时间。  

    举个例子:

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    12

    13

    14

    15

    16

    17

    #include<stdio.h>

    int main()

    {

       int j;

     

       printf("日期:%s\n",__DATE__);

     

       printf("时间:%s\n",__TIME__};

     

       printf("文件名:%s\n",__FILE__);

     

       printf("这是第%d行代码\n",__LINE__);

     

       printf("本编译器%s标准C\n",(__STD__)?"符合":"不符合");

       return 0;

     

    }

     

    6.2.重置行号和文件名命令------------#line

     
    使用__LINE__预定义宏名赈灾编译的程序行号。使用#line命令可改变预定义宏__LINE__与__FILE__的内容,该命令的基本形如下:
     #line number[“filename”]

    其中的数字为一个正整数,可选的文件名为有效文件标识符。行号为源代码中当前行号,文件名为源文件的名字。命令为#line主要用于调试以及其他特殊应用。
    举个例子:

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    1:#include<stdio.h>

    2:#include<stdlib.h>

     

    4:#line 1000

      

    6int main()

    7:{

    8:    printf("当前行号:%d\n",__LINE__);

    9:    return 0;

    10:}  

    在以上程序中,在第4行中使用#line定义的行号为从1000开始(不包括#line这行)。所以第5行的编号将为1000,第6行为1001,第7行为1002,第8行为1003.

     

    6.3.修改编译器设置命令 ------------#pragma
     
    #pragma命令的作用是设定编译器的状态,或者指示编译器完全一些特定的动作。#pragma命令对每个编译器给出了一个方法,在保持与C语言完全兼容的情况下,给出主机或者操作系统专有的特征。其格式一般为:

    1

    #pragma Para

    其中,Para为参数,可使用的参数很多,下面列出常用的参数:


    Message参数,该参数能够在编译信息输出窗口中输出对应的信息,这对于源代码信息的控制是非常重要的,其使用方法是:

    1

    #pragma message(消息文本)

    当编译器遇到这条指令时,就在编译输出窗口中将消息文本显示出来。


    另外一个使用比较多得pragma参数是code_seg.格式如:

    1

    #pragma code_seg([“section_name”[,section_class]])

    它能够设置程序中函数代码存放的代码段,在开发驱动程序的时候就会使用到它。

     

    参数once,可保证头文件被编译一次,其格式为:

    1

    #pragma once

    只要在头文件的最开始加入这条指令就能够保证头文件被编译一次。

     


    6.4.产生错误信息命令 ------------#error
     
    #error命令强制编译器停止编译,并输出一个错误信息,主要用于程序调试。其使用如下:

    1

    #error 信息错误  


    注意,错误信息不用双括号括起来。当遇到#error命令时,错误信息将显示出来。


    例如,以下编译预处理器命令判断预定义宏__STDC__,如果其值不为1,则显示一个错误信息,提示程序员该编译器不支持ANSI C标准。

    1

    2

    3

    4

    #if __STDC__!=1

     

       #error NOT ANSI C

    #endif

     

    七.内联函数
     
      在使用#define定义带参数宏时,在调用函数时,一般需要增加系统的开销,如参数传递,跳转控制,返回结果等额外操作需要系统内存和执行时间。而使用带参数宏时,通过宏替换可再编译前将函数代码展开导源代码中,使编译后的目标文件含有多段重复的代码。这样做,会增加程序的代码量,都可以减少执行时间。
      

      在C99标准钟,还提供另外一种解决方法:使用内联函数。
      在程序编译时,编译器将程序中出现的内联函数的调用表达式用内联函数的函数体来进行替代。显然,这种做法不会产生转去转回得问题。都是由于在编译时将函数体中的代码被替代到程序中,因此会增加目标代码量,进而增加空间的开销,而在时间开销上不像函数调用时那么大,可见它是以增加目标代码为代码来换取时间的节省。
      定义内联函数的方法很简单,只要在定义函数头的前面加上关键字inline即可。内联函数的定义与一般函数一样。例如,定于一个两个整数相加的函数:

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    12

    13

    14

    15

    16

    17

    18

    19

    20

    21

    22

    23

    24

    25

    26

    27

    28

    29

    30

    31

    32

    33

    34

    35

    36

    37

    #include<stdio.h>

     

    #include<stdlib.h>

     

      

     

    inline int add(int x,int y);

     

      

     

    inline int add(int x,int y)

     

    {

     

       return x+y;

     

    }

     

      

     

    int main()

     

    {

     

       int i,j,k;

     

       printf("请输入两个整数的值:\n");

     

       scanf("%d %d",&i,&j);

     

       k=add(i,j);

     

       printf("k=%d\n",k);

     

       return 0;

     

    }

      

    在程序中,调用函数add时,该函数在编译时会将以上代码复制过来,而不是像一般函数那样是运行时被调用。


    内联函数具有一般函数的特性,它与一般函数所不同之处在于函数调用的处理。一般函数进行调用时,要讲程序执行权转导被调函数中,然后再返回到调用到它的函数中;而内联函数在调用时,是将调用表达式用内联函数体来替换。在使用内联函数时,应该注意如下几点:

    1

    2

    在内联函数内部允许用循环语句和开关语句。但是,程序在经过编译之后,这个函数是不会作为内联函数进行调用的。

    内联函数的定义必须出现在内联函数第一次被调用之前。

     

    其实,在程序中声明一个函数为内联时,编译以后这个函数不一定是内联的,


    即程序只是建议编译器使用内联函数,但是编译器会根据函数情况决定是否使用内联,所以如果编写的内联函数中出现循环或者开关语句,程序也不会提示出错,但那个函数已经不是内联函数了。


    一般都是将一个小型函数作为内联函数。

    展开全文
  • c语言预处理命令

    2018-04-25 18:01:07
    预处理命令以符号“#”开头。宏定义命令:#define、#undef,用来定义和解除宏。(值得注意的是还可以定义带参数的宏)文件包含命令:#include "文件名" 或者 #include &lt;文件名&gt;。使用前者时...
  • 问关于C语言中的预处理命令 答 我们可以在C 源程序中插入传给 编译程序的各种指令这些指令被称为预处理器指令等价于汇编语言中的伪指令它们扩充了程序设计的环境 现把常用的 预处理命令总结如下 1. 预处理程序 按照...
  • C语言include预处理命令与多文件编译

    千次阅读 2018-04-27 10:56:17
    #include预处理命令几乎使我们在第一次接触C的时候就会碰到的预处理命令,可我现在还不怎么清楚,这次争取一次搞懂。一、#include预处理指令的基本使用预处理指令可以将别处的源代码内容插入到现在的位置,可以标识...
  • C程序的源代码中可包括各种编译指令,这些指令称为预处理命令。虽然它们实际上不是C语言的一部分,但却扩展了C程序设计的环境。本节将介绍如何应用预处理程序和注释简化程序开发过程,并提高程序的可读性。ANSI标准...
  • 问关于 C 语言中的预处理命令 答 我们可以在 C 源程序 中插入传给 编译程序 的各种指令这些指令被称为 预处理器指令等价于 汇编语言中的伪指令 它们扩充了程序设计的环境 现把常用的 预处理命令 总结如下 预处理程序...
  • 问关于 C 语言中的预处理命令 答 我们可以在 C 源程序 中插入传给 编译程序 的各种指令这些指令被称为 预处理器指令等价于 汇编语言中的伪指令 它们扩充了程序设计的环境 现把常用的 预处理命令 总结如下 1....
  • 一、对C语言的初步认识 二、C语言基本数据类型、操作符和表达式 三、...十、C语言中数据和存储类型 十一、C语言中的用户定义数据类型 十二、C语言编译预处理命令 1、宏定义和宏替换 2、文件包含处理 3、条件编译概念
  • C语言预处理命令#define的用法 define是C语言中的预处理命令,它用于宏定义,可以提高源代码的可读性,为编程提供方便。 预处理命令以“#”号开头,如包含命令#include,宏定义命令#define等。一般都放在源文件的...
  • C语言预处理命令

    千次阅读 2018-04-16 21:19:27
    预处理命令主要是改进程序设计环境,以提高编程效率,不属于c语言本身的组成部分,不能直接对它们进行编译,必须在对 程序编译之前,先对程序中的这些特殊命令进行“预处理”。比如头文件。有以下三类:宏定义,文件...
  • 预处理命令:以“#”符号开头的编译指令(预处理命令属于C语言编译器)预处理的主要作用: 1. 将源文件中以”#include”格式包含的文件复制到编译的源文件中 2. 用实际值替换使用”#define”定义的字符串 3. 根据...
  • c语言预处理命令

    2020-02-10 21:59:27
    c提供的预处理功能有: 宏定义 文件包含 条件编译 为了与其她c语句区分,命令经常以符号“#”开头。 宏定义 #define 标识符 字符串 可以避免反复输入字符串,后面不加;宏定义在默认时的有效范围是全部。也可以...
  • 预处理命令是在程序编译阶段进行执行的命令,用于编译与特定环境相关的可执行文件。预处理命令扩展了C语言。 一、宏替换命令 不用多讲,大家都懂。 #define 标识符 字符串 下面总结一些比较特殊的宏: 1、...
  • c语言预处理命令

    2015-01-11 13:13:06
    在前面各章中,已多次使用过以“#”号开头的预处理命令。如包含命令#include,宏定义命令#define等。在源程序中这些命令都放在函数之外,而且一般都放在源文件的前面,它们称为预处理部分。 所谓预处理是指在进行...
  • C语言常用预处理命令

    千次阅读 2019-02-25 19:42:25
    指令 含义 # 空指令,无任何效果,可以用来注释 ...包含一个源代码文件,头文件 ...如果给定条件为真,则编译下面代码 ...如果宏已经定义,则编译下面代码 ...如果#if条件不为真,当前条件为真,则编译下面代码 #...
  • c语言中的编译预处理命令

    千次阅读 2020-06-16 15:56:39
    1. 所有编译预处理语句以”#“开头 2. 每个预处理命令必须单独占一行 3. 语句末尾不使用分号作为结束符 4. 预处理语句主要有宏,条件编译和文件包含 1.无参宏 定义语句的格式如下: #define 标识符 字符串 作用: 用...
  • C语言预处理命令: ①宏定义 ②文件包含 ③条件编译 1.宏定义----#define ①不带参数的宏定义 #define PI 3.1415926 //①宏名一般习惯大写; //②宏定义只是简单的字符串替换,不做正确性检查,且不分配...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 1,321
精华内容 528
关键字:

c语言编译预处理命令

c语言 订阅