C语言预处理上

简介: C语言预处理上

1.预定义符号


下面的预定义符号都是语言内置的,我们可以直接使用


__FILE__//进行编译的源文件

__LINE__//当前行号

__DATE__//文件被编译的日期

__TIME__//文件被编译的时间


举个例子,打印当前文件被编译的日期和时间:


int main()
{
  printf("%s %s",__DATE__,__TIME__);
  return 0;
}


2.#define


#define定义标识符

语法:


#define name stuff

1

如:


#define MAX 1000
#define Peo Peoinfo

1

2

在程序中,可以直接使用这些标识符,举个例子:


#define MAX 1000
#define Peo Peoinfo
int main()
{
  int Peo = MAX;
}


要注意一点:


在define定义时,不要在最后加上;


#define MAX 1000;//在后续运行中会出现错误
#define MAX 1000//正确写法

1

2

在定义标识符时,如果像一下定义,会出现问题


#define A 1+3
#define B 4+3
int main()
{
  int c = A*B;
}


这里如果我们主观上会认为A就是1+3的值为4,B是4+3的值为7,所以在后面的替换后,int c = A*B替换成int c = 4*7,c的值就是28,其实这是错误的


在预处理中的替换是“直接替换”,预处理后int c = A*B会变为int c = 1+3*4+3,由于运算符有优先顺序,c的为16.


#define定义宏
#define 机制包括了一个规定,允许把参数替换到文本中,这种实现通常称为宏(macro)或定义宏(define macro)。

宏的申明方式如下:


#define name( parament-list ) stuff
1

parameter-list为参数列表,参数会出现在stuff中

注意:

参数列表的左括号必须与name紧邻,中间不能有空格

如果之间有空格存在,参数列表就会被解释为stuff中的一部分


接下来举一个例子

定义一个宏,这个宏接收一个参数x


#define SQUARE(x) x*x

1

将宏声明之后,在预处理中,例如SQUARE(5)就会被5*5所替换

#define SQUARE(x) x*x
int main()
{
  int num = SQUARE(5);
  printf("%d",num);//结果会输出5
}
1

面代码:


#define SQUARE(x) x*x
int main()
{
  int num = SQUARE(1+5);
  printf("%d",num);
}

,可能会认为这段代码打印结果是36,但事实上这个程序打印11


因为在替换文本时,参数x被替换成了1+5,所以语句变成了int num = 1+5*1+5


所以可以看出,由替换产生的表达式并没有按照预想的次序进行求值


其实在宏定义时,加上两个括号就可以解决这个问题


#define SQUARE(x) (x)*(x)

1

在预处理之后替换成:int num = (1+5)*(1+5)


继续观看一下代码:


#define SUM(x) (x)+(x)
int main()
{
  printf("%d",10*SUM(5));
}


这个代码仍有问题

在预处理后会替换成:


printf("%d",10*(5)+(5));
1

可以看出,由于表达式的优先次序,这个宏不会按照我们的想法进行正确计算


所以宏定义表达式两边加上一对括号就可以了


#define SUM(x) ((x)+(x))
1

用于对数值表达式进行求值的宏定义都应该用这种方式加上括号,避免在使用宏时由于参数中

的操作符或邻近操作符之间不可预料的相互作用。


#define 替换规则

在调用宏时,首先对参数进行检查,看看是否包含任何由#define定义的符号。如果是,它们首先被替换。

替换文本随后被插入到程序中原来文本的位置。对于宏,参数名被他们的值所替换。

最后,再次对结果文件进行扫描,看看它是否包含任何由#define定义的符号。如果是,就重复上述处理过程。

宏参数和#define 定义中可以出现其他#define定义的符号。但是对于宏,不能出现递归。

当预处理器搜索#define定义的符号的时候,字符串常量的内容并不被搜索。

#和##

#的作用是


把宏的参数插入到字符串中


首先我们先看一个代码:


printf("hello ""world");
1

我们将"hello world"分写成2个字符串,运行代码后,仍然输出hello world

所以可以看出字符串是有自动连接的特点的


再看一个代码:


int main()
{
  printf("the size of int is %d\n", sizeof(int));
  printf("the size of char is %d\n", sizeof(char));
  printf("the size of short is %d\n", sizeof(short));
  printf("the size of float is %d\n", sizeof(float));
  printf("the size of double is %d\n", sizeof(double));
  return 0;
}


如果我们想要计算每个类型的大小,并且要同字符串一块打印出来,每打印一次都需要写一段字符串,而且字符串中的要写的类型还不同,十分麻烦

所以我们可以使用宏


所以可以在定义宏时,通过使用#,把参数插入字符串中


#define PRINT(type,size) printf("the size of " #type" is %d\n",size)
1

所以在使用宏时,就十分方便


int main()
{
  PRINT(int, sizeof(int));
  PRINT(char, sizeof(char));
  PRINT(short, sizeof(short));
  //……………………………………………………
  return 0;
}


##的作用是:


##可以把位于它两边的符号合成一个符号。

它允许宏定义从分离的文本片段创建标识符。


观察一下代码:


#define COMBINE(x,y) x##y
int main()
{
  int abcd = 10;
  printf("%d\n", COMBINE(ab, cd));//结果输出10
  return 0;
}


通过使用宏,##将x和y合成一个符号,在预处理后语句变为:printf("%d\n",abcd);


注意:这样的连接必须产生一个合法的标识符。否则其结果就是未定义的。



目录
相关文章
|
2月前
|
编译器 C语言
C语言的预处理指令
C语言的预处理指令
|
2月前
|
编译器 Linux PHP
C语言从入门到实战——预处理详解
C语言预处理是C语言编译过程的一个阶段,它在编译之前对源代码进行一系列的处理操作,包括宏替换、文件包含、条件编译等,最终生成经过预处理的代码,然后再进行编译。
47 0
|
5月前
|
存储 自然语言处理 编译器
『C语言进阶』程序环境和预处理
『C语言进阶』程序环境和预处理
|
1天前
|
编译器 C语言
C语言:预处理
C语言:预处理
6 1
C语言:预处理
|
10天前
|
存储 Linux C语言
C语言进阶第十一节 --------程序环境和预处理(包含宏的解释)-2
C语言进阶第十一节 --------程序环境和预处理(包含宏的解释)
|
10天前
|
自然语言处理 Linux 编译器
C语言进阶第十一节 --------程序环境和预处理(包含宏的解释)-1
C语言进阶第十一节 --------程序环境和预处理(包含宏的解释)
|
15天前
|
编译器 Linux C语言
C语言:预处理详解(知识点和代码演示)
C语言:预处理详解(知识点和代码演示)
|
2月前
|
存储 编译器 程序员
【程序环境和预处理】C语言
【程序环境和预处理】C语言
|
2月前
|
存储 机器学习/深度学习 自然语言处理
【进阶C语言】编译与链接、预处理符号详解
【进阶C语言】编译与链接、预处理符号详解
28 0
|
2月前
|
存储 自然语言处理 编译器
【C语言进阶】程序环境和预处理
【C语言进阶】程序环境和预处理