C语言预处理详解

目录

(一)预处理符号

(二)define定义常量和宏

(三)#符号和##符号

(四)undef符号的条件编译

(五)头文件的包括


(一)预处理符号

在预处理中,有一些它本身就定义的符号

__DATE__;//定义了当前的日期
__TIME__;//定义了当前的时间
__LINE__;//定义了当前的行数
__FILE__;//定义了当前的文件
__STDC__;//如果当前的编译器支持ANSI标准,则返回1,否则为0;

这些符号是预处理中定义的,可以直接使用。比如

printf("%d", __LINE__);//打印当前的行数
printf("%s", __TIME__);//打印当前的时间

(二)define定义常量和宏

define可以定义常量和宏。比如

#define ADD(x, y) x+y

这里就定义了一个宏。当编译进行预处理的时候,编译器会ADD(x, y)替换成x+y。#define 机制包括了⼀个规定,允许把参数替换到⽂本中,这种实现通常称为宏(macro)或定义宏。

#define π 3.14

这里就define定义了一个常量。当编译进行预处理时,会把π替换成3.14。不过define并不会像人一样的想当然,它是十分严谨的。进行替换的替换,它把它替换好的合并成一个新语句,并按优先级进行计算。比如

#define SQUARE( x ) x * x
int a = 5;
printf("%d\n" ,SQUARE( a + 1) );

很多人以为结果是36,可实际运行起来就不是这回事了。事实上,它在预处理后会变成

printf ("%d\n",a + 1 * a + 1 );

所以优先级就变了,算出来的结果也就不同了。所以我们再define定义宏时,要往往考虑打括号,让它实际运行起来的时候符合我们的预期。

#define SQUARE (x*x)

这样计算就符合预期了。此外,不要在定义常量和宏的时候加分号;,因为会替换,如果替换的后面有;就可能造成编译错误。

(三)#符号和##符号

#符号可以把宏的参数字符化。它仅出现在宏中。当我们有⼀个变量 int a = 10; 的时候,我们想打印出: the value of a is 10 . 就可以写成下面的形式。当我们按照下⾯的⽅式调⽤的时候: PRINT(a);//当我们把a替换到宏的体内时,就出现了#a,⽽#a就是转换为"a",

#define PRINT(n) printf("the value of "#n " is %d", n);

##符合则是把两个符号连接起来变成一个符号。连接的符号必须是定义过的,否则会编译失败。

int int_max(int x, int y)
{
return x > y ? x : y;
}
float float_max(float x, float y)
{
return x > y ? x : y;
}

可以写成

//宏定义
#define GENERIC_MAX(type) \
type type##_max(type x, type y)\
{ \
return (x>y?x:y); \
}
(四)undef符号的条件编译

undef是用来移除宏的。

#undef NAME
//如果现存的⼀个名字需要被重新定义,那么它的旧名字⾸先要被移除。

我们可以选择性的选择要编译的代码,通过条件编译来实现。比如

#include <stdio.h>
#define __DEBUG__
int main()
{
    int i = 0;
    int arr[10] = {0};
    for(i=0; i<10; i++)
    {
        arr[i] = i;
        #ifdef __DEBUG__
        printf("%d\n", arr[i]);//为了观察数组是否赋值成功。
        #endif //__DEBUG__
    }
    return 0;
}

如果我们宏定义过__DEBUG__,则运行到#ifdef __DEBUG时,就会编译到#endif。相当于上了一个开关。否则的话,就直接跳过这一块进行接下来的编译。

//常见的编译条件
1.
#if 常量表达式
//...
#endif
//常量表达式由预处理器求值。
如:
#define __DEBUG__ 1
#if __DEBUG__
//..
#endif
2.多个分⽀的条件编译
#if 常量表达式
//...
#elif 常量表达式
//...
#else
//...
#endif
3.判断是否被定义
#if defined(symbol)
#ifdef symbol
#if !defined(symbol)
#ifndef symbol
4.嵌套指令
#if defined(OS_UNIX)
#ifdef OPTION1
unix_version_option1();
#endif
#ifdef OPTION2
unix_version_option2();
#endif
#elif defined(OS_MSDOS)
#ifdef OPTION2
msdos_version_option2();
#endif
#endi
(五)头文件的包括

有两种方式来包括头文件

#include <stdio.h>
#include "stdio.h"

第一种会直接从系统的指定路径去找头文件,找不到则编译失败,一般适用于库文件。而第二种头文件的包括,它先会从当前目录去寻找头文件,如果找不到,再去指定文件去寻找。所以我们库文件的包括,既可以用第一种又可以用第二种。只不过第二种慢一点而已。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值