预处理器

预处理器

预定义符号

由预处理器定义的符号

 // 进行编译的源文件名称
    __FILE__
    // 文件当前行号
    __LINE__
    // 文件被编译的日期
    __DATE__
    // 文件被编译的时间
    __TIME__
    // 如果编译器遵循ANSI C,值为1,否则未定义
    __STDC__

#define

#define reg register//将reg定义为register修饰符,为register修饰符创建了一个别名
#define  do_forever  for( ; ; )//用do_forever代表无限循环
#define  CASE  break;case//用来方便记忆
#define peintf  \
for(int i=0;i<5;i++)\
    printf("*");
#include<stdio.h>
#include<stdlib.h>
#include<string.h>

int main() 
{
    peintf
    return 0;
}

#define机制包含一个设定,允许将参数替换到文本中,这种实现方式叫做宏或者定义宏

#define name(parameter-list)  stuff//宏的声明方式

举一个例子

#define  square(x)  x*x//将参数x替换为x*x
//但是这个写法是有问题的,如果有表达式square(a+1)
//那么表达式就会变为a+1*a+1,就会发生错误
//因此,可以改为(x)*(x),但是还是有问题
//如果有表达式10*add(a+1)
//表达式就变为10*(a+1)+(a+1),结果依然不对
//最终答案是((x)*(x))

来看宏的应用

#define  a  do
#define  b(x)  while((x))
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
//这样a和b就构成了新的语句
int main() 
{
    int i = 0;
    a{
        printf("*\n");
        i++;
    }b(i<5);
    return 0;
}

#define的替换

在调用宏的时候,会先检查参数,观察是否有#define定义的符号,如果有他们将首先被替换

替换文本被放到原先文本的地方,对于宏,参数名被他们的值所代替

最后,再次对结果文本进行扫描,检查是否还有#define定义的符号,如果有就重复上述流程

宏与函数

相对于宏来说,函数有两点不足:一是函数的调用和返回需要的代码量较大,在简单的小型计算方面,宏相对更加具有优势,

二是函数对参数有类型要求,有着应用局限性,而宏与类型无关

但是宏的缺点是每次使用宏时都会将宏的副本复制一遍,加大代码量

下面展示一个宏比函数更有优势的例子:

#define   MALLOC(type,n)  (type,n)\
          (type*)malloc(n*sizeof(type))

宏的副作用

参数求值方面,参数每次用于宏定义时,他们都会重新求值,由于多次求值,具有副作用的参数可能产生永久性影响

#undef

解除指定的宏定义,当想重新定义一个已有宏时,需要先解除原先的宏

更多关于宏

C语言宏的定义和宏的使用方法(#define) (biancheng.net)

条件编译

条件编译的基本结构为#if指令和与其匹配的 #endif指令,如果多条件还可以增加#elif和 #else指令,#elif没有数量限制,#else只有在前面语句全部为假时才能生效

#if constant-expression
       statements;
#elif  constant-expression
        other statements;
#else  constant-expression
#endif

文件包含

#include指令使得另一个文件的内容被编译,其执行过程相对简单,预处理器将该指令删除,并用包含文件的内容代替,如果一个头文件被包含到10个源文件,那么它将被编译10次,但是这所引起的开销是不必担心的,因为这种开销非常小,且发生在编译时期,对运行效率影响不大

posted @ 2023-05-28 10:58  alexlance  阅读(32)  评论(0编辑  收藏  举报