C语言|程序的编译和链接(2)

目录

前言

1.预定义符号

 2.#define

2.1 #define定义标识符

2.2.#define定义宏

2.3 #define 替换规则

2.4.#的作用

​编辑 2.5.##的作用

 2.5.带有副作用的宏参数

总结



前言

前面我们笼统地介绍过了翻译环境和运行环境。接下来,我们会进一步去了解它们。


一、预处理

1.预定义符号

__FILE__   //进行编译的源文件

__LINE__  //文件当前的行号

__DATE__ //文件被编译的日期

__TIME__ //文件被编译的时间

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

#include<stdio.h>
int main()
{
	printf("file:%s\n",__FILE__);
	printf("line:%d\n", __LINE__);
	printf("date:%s\n", __DATE__);
	printf("time:%s\n", __TIME__);
	return 0;
	
}

 输出结果:

 2.#define

2.1 #define定义标识符

#include<stdio.h>
#define  M   20
int main()
{
	int a = 0;
	a = M;
	printf("%d", a);
	return 0;
}

这里一定要注意#define语句后面没有加分号!!! 很容易出问题的。

2.2.#define定义宏

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

宏的申明方式:

#define name(parament-list) stuff

例:

#include<stdio.h>
#define  MAX(x,y) (x)>(y)?(x):(y)
int main()
{
	int a = 1;
	int b = 2;
	printf("%d",MAX(a, b));
	return 0;
}

虽然看似简单,但是还有一些需要注意的点哟~我们再看一下下面的代码:

#include<stdio.h>
#define  SQUARE(x) x*x
int main()
{
	printf("%d",SQUARE(2+3));
	return 0;
}

 运行结果是11。

我们的原意是想打印5*5的,为什么结果是11呢?原来替换后的结果长这样:

#include<stdio.h>
int main()
{
	printf("%d",2+3*2+3);
	return 0;
}

 2+3*2+3=11。这就对上了。我们就要修改一下我们的代码,加上括号。

#include<stdio.h>
#define  SQUARE(x) (x)*(x)
int main()
{

	printf("%d",SQUARE(2+3));
	return 0;
}

这样子就能得出我们想要的结果了。

 

 紧接着看下一个代码:
 

#include<stdio.h>
#define DOUBLE(x) (x)+(x)
int main()
{
	printf("%d",2*DOUBLE(5));
	return 0;
}

 运行结果:

我们这边本来是想算2*(5+5)的,结果应该是20。原来替换的结果是这个样子的:|

#include<stdio.h>
int main()
{
	printf("%d",2*5+5);
	return 0;
}

2*5+5=15。这个结果也就对上了。

所以,我们需要加括号的时候一定要加括号。大家千万不能贪图一下子的省事,不在#define语句加括号,而是在用的时候加,那样子就是一逸永劳了。

2.3 #define 替换规则

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

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

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

【注意点】

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

举个例子:

#include<stdio.h>
#define M 10
#define DOUBLE(x) ((x)+(x))
int main()
{
	printf("%d",DOUBLE(M));
	return 0;
}

这是可以运行的,没有报错。

//error
#include<stdio.h>
#define M 10
#define DOUBLE(x) ((x)+(x))
#define ADD(c,d) ((c)+(d))
int main()
{
	int a = 1;
	int b = 2;
	printf("%d",DOUBLE(ADD(a,b)));
	return 0;
}

 而这个样子的代码,就会报错。

2.当预处理器搜索#define定义的符号是,字符串常量的内容并不会被搜索到。

#include<stdio.h>
#define M 10
int main()
{
	printf("M");
	return 0;
}

2.4.#的作用

使用#,把一个宏参数变成对应的字符串。

#include<stdio.h>
#define PRINT(val,format) printf("the value of "#val" is "format"\n",val)
int main()
{
	int a = 10;
	PRINT(a, "%d");
	int b = 20;
	PRINT(b, "%d");
	float f = 3.5f;
	PRINT(f, "%f");
	return 0;
}

运行结果如下: 

 2.5.##的作用

##可以把位于它两边的符号合成一个符号。它允许宏定义从分离的文本片段创建标识符。

#include<stdio.h>
#define CAT(a,b) a##b
int main()
{
	int xy =1;//定义我们要合成的符号
	printf("%d", CAT(x, y));
	return 0;
}

 2.5.带有副作用的宏参数

当宏参数在宏的定义中出现超过一次时,如果参数带有副作用,那么我们在使用这个宏的时候就可以出现危险,导致不可预测的后果。副作用就是表达式求值的时候出现的永久性效果。

如:

#include<stdio.h>
#define MAX(x,y) ((x)>(y)?(x):(y))
int main()
{
	int a = 3;
	int b = 4;
	int m = MAX(++a,++b);
	printf("m=%d a=%d b=%d",m,a,b);
}

 这里我们的结果是:

我们来解释一下,我们的结果为什么是6,4,6。

int m=MAX(++a,++b)
#可以替换成:
int m=((++a)>(++b)?(++a):(++b))
       3+1=4   4+1=5
         4<5              5+1=6
m=                            6
a=      4
b=                            6


总结

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值