关于预处理#

1. 能用宏定义开始或者结束一段注释吗?
例如:
#define BSC //
#define BMC /*

#define EMC */
那么:
BSD my single-line comment
BMC my single-line comment EMC
正确吗?
答案是不正确的,这是因为注释先于预处理指令被处理,当这两行被展开成//...或者/**/时,注释已被处理完毕,此时再出现替换而成的//或者自然会发生错误。
2. 请看下面这样一组宏定义,z的值最后是多少?
#define X 3
#define Y X*2
#undef X
#define X 2
int z = Y;
答案:4;
当代码在编译的时候,进行替换,而#undef是解除X的定义,也就是上面的3;再解除之后,重新定义了X为2,这个时候Y = 2*2 = 4.
3. 条件编译的几种形式;
a.如果标示符已被#define命令定义过,则对程序段1进行编译;否则对程序段2进行编译,格式如下:
#ifdef 标示符
程序段1
#else
程序段2
#endif
其中,如果程序段2为空,#else也可以没有。
b. 如果标示符未被#define命令定义过,则对程序段1进行编译,与第一种形式功能相反,格式如下: 
#ifndef 标示符
程序段1
#else
程序段2
#endif
c. 如果常量表达式的值为真(非0),则对程序段1进行编译,否则对程序段2进行编译,因此可以使程序在不同
条件下,完成不同的功能,格式如下:
#if 常量表达式
程序段1
#else
程序段2
#endif

d. #ifndef和#define
    #ifndef x//先测试x是否被宏定义过
  #define x
  程序段1 //如果x没有被宏定义过,定义x,并编译程序段1
  #endif
    程序段2 //如果x已经定义过了则编译程序段2的语句,“忽视”程序段1。
    条件指示符#ifndef 的最主要目的是防止头文件的重复包含和编译。了解:条件编译当然也可以用条件语句来实现。 但是用条件语句将会对整个源程序进行编译,生成的目标代码程序很长,而采用条件编译,则根据条件只编译其中的程序段1或程序段2,生成的目标程序较短。如果条件选择的程序段很长,采用条件编译的方法是十分必要的。
 
  <标识>在理论上来说可以是自由命名的,但每个头文件的这个“标识”都应该是唯一的。标识的命名规则一般是头文件名全大写,前后加下划线,并把文件名中的“.”也变成下划线,如:stdio.h
  #ifndef _STDIO_H_
  #define _STDIO_H_
  ......
  #endif
4. 关于#error预处理
作用:编译程序时,只要遇到#error就会生成一个编译错误提示消息,并停止编译。
语法格式:#error error-message
注意:宏串error-message不用双引号包围。
这个命令一般是放在异常处理代码段中,如果出现编译错误,可以输出信息帮助你确定出现错误的地方。
5. 关于#line 预处理
作用:改变当前行数和文件名称
形式:#line number["filename"]
注意:[]内的文件名可以省略。
例如:#line 30 "a.h"或者#line 30
改变当前行号为30,当前文件名为a.h;这样做有什么意义?
平时我们基本上用不上,有些时候还是有一点点作用的,那就是在编译器的编写中,我们知道编译器对C源码编译过程中会产生一些中间文件,通过这条命令,可以保证文件名是固定的,不会被中间文件代替,有利于进行分析。
6. 关于#pragma预处理
作用:设定编译器的状态或者指示编译器完成一些特定的动作;#pragma指令对每个编译器给出了一个方法,在保持C和C++语言完全兼容的情况下,给主机或者OS专有的特征,因为每个编译器上的编译指示都不同。
格式:#pragma para
说明:para为参数,参数有很多种,例如:
a. #pragma message
eg:
#ifdef _X86
#pragma message("_X86 macro activated!")
#endif
说明:当我们定义了_X86这个宏之后,应用程序在编译时就会在编译输出窗口显示
"_X86 macro activated!",这样我们就不会因为忘记自己定义的一些特定的宏而苦思冥想了。
b. #pragma once
作用:保证头文件被编译一次。
c. #pragma comment(...)
作用:将一个注释记录放入一个对象文件或者可执行文件中,常用lib关键字,可以帮我们连入一个库文件,例如:
#pragma comment(lib,"user32.lib")
该指令用来将user32.lib库文件加入到本工程中,有时候目录分层要用到.和..,其中.代表当前目录,..代表上一级目录。
d. #pragma code_seg
作用:设置程序中函数代码存放的代码段,经常用在驱动开发中。
...还有很多,so much...
如果想知道每种参数代表什么作用,可以查阅相关资料,或者用到的时候可以查阅相关知识。
7. #运算法
#也可以当预处理用?答案是yes.
eg:
#define SQR(x) printf("The square of x is %d.\n",((x)*(x)));
如果这样使用宏:
SQR(8);
则输出为:
The square of x is 64.
这里的x是被当做普通文本来处理。
假如你确定希望在字符串中包含宏参数,那我们就可以使用"#",它可以把语言符号转化为字符串
eg:
#define SQR(x) printf("The square of "#x" is %d.\n",((x)*(x)));
如果使用SQR(8);
则输出的是:
The square of 8 is 64.
8. ##预算符
作用:用作宏函数的替换部分,把两个语言符号组合成单个语言符号。
eg:
#define XNAME(n) x##n
如果使用XNAME(8)
则展开后为:
x8
##就相当于一个粘合剂,将前后两部分粘合起来。

(The End)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值