预编译(1)

目录

预定义符号:

使用:

结果:

预编译前后对比:

#define定义常量:

基本语法:

举例1:

结果:

预编译前后对比:

 举例2:

预编译前后对比:

 注意事项:

#define定义宏:

下⾯是宏的申明⽅式:

举例:

使用:

 预编译前后对比:

 结果:

 注意事项:

1.参数列表的左括号必须与name紧邻,如果两者之间有任何空白存在,参数列表就会被解释为stuff的一部分。

举例:

正确的:

错误的:

2.不够严谨的写法导致的失误:

举例:

结果:

使用预编译进行查看替换的情况:

所以严谨的写法应该是:

带有副作用的宏:

 举例:

 当我们使用a++和b++这种带有永久性的效果时:

 预编译前后对比:​编辑

结果:

分析:

宏的替换规则:


预定义符号:

C语⾔设置了⼀些预定义符号,可以直接使⽤,预定义符号也是在预处理期间处理的。

__FILE__ //进⾏编译的源⽂件
__LINE__ //⽂件当前的⾏号
__DATE__ //⽂件被编译的⽇期
__TIME__ //⽂件被编译的时间
__STDC__ //如果编译器遵循ANSI C,其值为1,否则未定义

使用:

int main()
{ 
    printf("%s\n", __FILE__);
    printf("%d\n", __LINE__);
    printf("%s\n", __DATE__ ;
    printf("%s\n", __TIME__);
}

结果:

预编译(1)_第1张图片 

预编译前后对比:

预编译(1)_第2张图片 

#define定义常量:

基本语法:

#define name stuff

举例1:

int main()
{
   int a = Mprintf("%d\n",M);
   printf("%s\n",STR);
   return 0 :
}
结果:

 预编译(1)_第3张图片

预编译前后对比:

 预编译(1)_第4张图片

 举例2:

#define forever for( ; ; )
int main()
{
    int a = M;
    printf("%d\n",M);printf("%s\n",STR);
    forever;
    return 0;
}

结果是无限循环

预编译前后对比:

 预编译(1)_第5张图片

 注意事项:

在define定义标识符的时候,不要在最后加上 ;  

#define定义宏:

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

下⾯是宏的申明⽅式:

 #define name( parament-list ) stuff

举例:

#define SOAURE(X) X*X

使用:

#define SOAURE(X) X*X
int main()
{
  int a = 5;
  printf("%d\n",SQUARE(a));
  return 0;
}
 预编译前后对比:

预编译(1)_第6张图片

 结果:

预编译(1)_第7张图片

 注意事项:

1.参数列表的左括号必须与name紧邻,如果两者之间有任何空白存在,参数列表就会被解释为stuff的一部分。

举例:
正确的:
#define SQUARE(X) X*X
错误的:
#define SQUARE (X) X*X

错误在于SQUARE举例(x)之间有一个空格,正常来说是不因该又间隔的,这二者应该紧贴在一起,也就是换在原型上来说,name应该和 ( parament-list )紧贴着!

2.不够严谨的写法导致的失误:

举例:
#define SOAURE(X) X*X
int main()
{
  int a = 5;
  printf("%d\n",SQUARE(a+2));
  return 0;
}

按照我们的想法因,再进行#define替换后,应该是(a+2)*(a+2),因为a=5,所以最后的结果因该是7*7=49,但是结果并不是如此。

结果:

预编译(1)_第8张图片

使用预编译进行查看替换的情况:

预编译(1)_第9张图片 

并不是我们想象中的 (a+2)*(a+2),而是a+2*a+2,也就是5+2*5+2=5+10+2=17

所以严谨的写法应该是:
#define SQUARE (X) ((X)*(X))

 以此避免因为不严谨而带来的错误。

带有副作用的宏:

当宏参数在宏的定义中出现超过一次的时候,如果参数带有副作用,那么你在使用这个宏的时候就可能出现危险导致不可预测的后果。

副作用就是表达式求值的时候出现的永久性效果。 

 举例:

#define MAX(a, b) ((a)>(b)?(a):(b))

 当我们使用a++和b++这种带有永久性的效果时:

int main()
{
   int a = 15;
   int b = 9;
   int m = MAX(a++, b++);
   printf("%d\n",m);
   printf("a=%d b=%d\n",a,,b);
   return 0;
}

 预编译前后对比:
预编译(1)_第10张图片

结果:

预编译(1)_第11张图片 

分析:

通过宏的替换,将   int m = MAX(a++, b++);替换为了int m = ((a++)>(b++)?(a++):(b++));

也正是因为替换,导致了++的不确定性。

  1. 1.因为a=15,再(a++)>(b++)中进行了使用,使用完后 a和b都因为++加上了1
  2. 2.因为再(a++)>(b++)中a比b大,所以执行?(a++):(b++));因为是a大,所以只执行(a++),所以最后答案输出给m的是16,但是输出完后,进行++执行,所以a又继续+1,得到17

宏的替换规则:

通过上诉我们得知了,宏是先把对应的内容替换掉,再进行运算。

而在程序中扩展#define定义符号和宏时,需要涉及⼏个步骤。

  1. 在调⽤宏时,⾸先对参数进⾏检查,看看是否包含任何由#define定义的符号。如果是,它们⾸先 被替换。
  2. 替换⽂本随后被插⼊到程序中原来⽂本的位置。对于宏,参数名被他们的值所替换。  
  3. 最后,再次对结果⽂件进⾏扫描,看看它是否包含任何由#define定义的符号。如果是,就重复上 述处理过程。

你可能感兴趣的:(文件操作,数据存储,C语言,数据存储,文件操作,c语言)