C++ "#"的作用和使用方法
本系列文章由 @yhl_leo 出品,转载请注明出处。
文章链接: http://blog.csdn.net/yhl_leo/article/details/48879093
1 #和##的作用和使用方法
C/C++ 的宏中,#的功能是将其后面的宏參数进行字符串化操作。简单说就是在对它所引用的宏变量通过替换后在其左右各加上一个双引號。##连接符号由两个井号组成,其功能是在带參数的宏定义中将两个子串联接起来,从而形成一个新的子串。
但它不能够是第一个或者最后一个子串。
#include <iostream>
using namespace std;
#define WARN_IF(EXP) if(EXP) cerr << #EXP << endl;
#define paster( n ) cout << "token" << #n << " = " << n << endl;
#define _CONS(a, b) int(a##+##b)
#define _STRI(s) #s
void main()
{
int div = 0;
WARN_IF(div == 0); // prints : div == 0
paster(9); // prints : token9 = 9
cout << _CONS(1, 2) << endl; // prints : 3
cout << _STRI(INT_MAX) << endl; // prints : INT_MAX
}
凡是宏定义里实用#或##的地方宏參数是不会再展开,比如_STRI(INT_MAX)中的INT_MAX就不会被展开为2147483647。
假设想要使当中的宏參数展开,则须要多加一层中间转换宏:
#define STRI(s) _STRI(s)
cout << STRI(INT_MAX) << endl; // prints : 2147483647
加这层宏的用意是把全部宏的參数在这层里全部展开。那么在转换宏里的宏就能得到对应的宏參数。
接下来,我们来了解通过预处理指令创建条件编译參数控制代码编译的一些使用方法。
2 #include的使用方法
包括头文件的操作,通常有两种格式:
#include <header-file>
#include "header-file"
<>和""表示编译器在搜索头文件时的顺序不同:
<>表示从系统文件夹下開始搜索,然后再搜索PATH环境变量所列出的文件夹,不搜索当前文件夹""是表示从当前文件夹開始搜索,然后是系统文件夹和PATH环境变量所列出的文件夹。
所以,系统头文件一般用<>,用户自定义的则能够使用"",加快搜索速度。
除此外,写代码多了就会发现,有些头文件之间的相互包括是有隐藏依赖关系的。一定要加以注意。Google C++ Style Guide中也强调使用标准的头文件包括顺序可增强可读性, 避免隐藏依赖:
1 相关文件(优先位置,如
dir2/foo2.h)
2 C系统文件
3 C++ 系统文件
4 其它库的.h文件
5 本项目内.h文件
3 #if,#elif,#else,#endif使用方法
// structure 1
#if constant_expression
#else
#endif
// structure 2
#if constant_expression
#elif constant_expression
#endif
这里的结构跟常见的if...else和if...else if...else语句相似,当#if后的条件为非零(true)时,编译#if和#else或#elif之间的代码。否则编译#else和#endif之间的代码(或者推断#elif后的条件是否非零(true),决定是否编译#elif和#endif之间的代码)。
#if 1
cout << "Hello world!" << endl;
#else
cout << "Nice to meet you!" << endl;
#endif
// prints : Hello world!
#if 1
cout << "Hello world!" << endl;
#elif 1
cout << "Nice to meet you!" << endl;
#endif
// prints: Hello world!
// Nice to meet you!
4 #define,#undef,#ifdef,#ifndef使用方法
#define是大家都常见的宏定义方法。使用方法结构为:
// #define identifier replacement-code
#define PI 3.1415926
#define ADD(x,y) (x + y)
#undef顾名思义。就是从该处取消前面已经定义的宏,假设标识符当前没有被定义称为一个宏名称,就会忽略该指令:
// #undef identifier
#undef PI
#ifdef和#ifndef 含义相反,前者含义为假设定义了该宏。则编译对应代码;后者则为假设未定义该宏。则编译对应代码。通用结构为:
/*
* #ifdef identifier
* #else or #elif
* #endif
**/
#define DEBUG
#ifdef DEBUG
cout << "This is a debug message." << endl;
#endif
// prints : This is a debug message.
/*
* #ifndef identifier
* #else or #elif
* #endif
**/
#ifndef DEBUG
cout << "This is a debug message." << endl;
#endif
// prints nothing
在编程时,为了避免头文件重定义,常常使用的就是#define配合条件编译解决:
#ifndef MY_HEADER_FILE_H
#define MY_HEADER_FILE_H
// ...
class MyHeaderFile
{
// ....
};
#endif // MY_HEADER_FILE_H
除此以外,还有#pragma once的使用方法,仅仅要在头文件的最開始增加这条指令就能够保证头文件被编译一次。
(在全部的预处理指令中,#pragma指令可能是最复杂的了,它的作用是设定编译器的状态或者是指示编译器完毕一些特定的动作,本文不多讲述。)
5 #line使用方法
#line命令是用于更改__LINE__ 和 __FILE__变量的值。
__FILE__和__LINE__描写叙述被读取的当前文件和所在行数。
// #line line-number filename
int main()
{
#line 10 "main.cpp"
cout << __FILE__ << " " << __LINE__ << endl;
}
// prints : main.cpp 10
6 #error使用方法
#error会直接导致程序停止编译并输出指定的错误信息:
// #error message
#ifndef VERSION
#error Version number not specified.
#endif
// The compiler will halt compiling and return with the specified error message:
// fatal error C1189: #error : Version number not specified.
C++ "#"的作用和使用方法的更多相关文章
- JAVA 注解的几大作用及使用方法详解
JAVA 注解的几大作用及使用方法详解 (2013-01-22 15:13:04) 转载▼ 标签: java 注解 杂谈 分类: Java java 注解,从名字上看是注释,解释.但功能却不仅仅是注释 ...
- serialVersionUID的作用以及设置方法(转)
声明:本篇文章是转载的 http://blog.csdn.net/kakaxi_77/article/details/8129070 http://snowlotus.iteye.com/blog/2 ...
- 在Android开发中替换资源图片不起作用的解决方法
现象 在android开发中,经常会需要替换res\drawable中的图片,打开res\layout下的文件预览布局页面发现图片已经被替换,但在模拟器或者真实机器上运行时发现该图片并没有被替换,还是 ...
- 【转】 PreTranslateMessage作用和使用方法
PreTranslateMessage作用和使用方法 PreTranslateMessage是消息在送给TranslateMessage函数之前被调用的,绝大多数本窗口的消息都要通过这里,比较常用, ...
- Linux中PATH环境变量的作用和使用方法
关于PATH的作用:PATH说简单点就是一个字符串变量,当输入命令的时候LINUX会去查找PATH里面记录的路径.比如在根目录/下可以输入命令ls,在/usr目录下也可以输入ls,但其实ls这个命令根 ...
- PHP trim()函数的作用和使用方法
PHP trim()函数一般是用来去除字符串首尾处的空白字符(或者其他字符),一般在用在服务端对接收的用户数据进行处理,以免把用户误输入的空格存储到数据库,下次对比数据时候出错. 该函数有两个参数,第 ...
- PreTranslateMessage作用和使用方法
PreTranslateMessage作用和使用方法 PreTranslateMessage是消息在送给TranslateMessage函数之前被调用的,绝大多数本窗口的消息都要通过这里,比较常用, ...
- header中Content-Disposition的作用与使用方法
下载文件的时候会使用: Content-disposition 是 MIME 协议的扩展,MIME 协议指示 MIME 用户代理如何显示附加的文件.Content-disposition其实可以控制用 ...
- 类属性与对象实现,init方法的作用,绑定方法,绑定方法与普通函数的区别,继承,抽象与继承,派生与覆盖
今日内容: 1.类属性与对象属性 2.init方法的作用 3.绑定方法 4.绑定方法与普通函数的区别(非绑定方法) 5.继承 6.抽象与继承 7.派生与覆盖 1.类属性与对象属性 类中应该进存储所有对 ...
随机推荐
- 群论 - Group Theory
群的定义 若非空集合\(G\)和定义在\(G\)上的二元运算\(⋅\)构成的代数结构\((G,⋅)\),满足: 封闭性:\(\forall a,b\in G\),有\(a⋅b\in G\). 结合律: ...
- maven项目中配置mvn源
在pom.xml中配置 <repositories> <!--for others--> <repository> <id>alimaven</i ...
- 关于element-ui select组件change事件只要数据变化就会触发的解决办法
使用select组件和表格组件结合起来用,但是发现在点击下一页的时候,由于select当中的数据发生了变化,所以也会触发select当中的change事件,但是我只希望在我主动改变select组件当中 ...
- Gcd(bzoj 2818)
Description 给定整数N,求1<=x,y<=N且Gcd(x,y)为素数的数对(x,y)有多少对. Input 一个整数N Output 如题 Sample Input 4 Sam ...
- 【CF711C】Coloring Trees(DP)
题意:给你n个数字,一共有m种,如果某数为0则该数为空,空的地方可以填任意种类数,但每填一个数字都要花费一定的费用, 从头到尾,所有相邻且相同的数字看作一个集合,求使n个数字的集合数为k所需的最小费用 ...
- 眉目传情之匠心独运的kfifo【转】
转自:http://blog.csdn.net/chen19870707/article/details/39899743 权声明:本文为博主原创文章,未经博主允许不得转载. 目录(?)[-] 一 ...
- wpf GridControl selectAll UnSelect
<Window x:Class="WpfApplication1.GridControlView" xmlns="http://schemas.microsoft. ...
- 51nod 1088 最长回文子串 【中心拓展法/输出长度和路径】
1088 最长回文子串 基准时间限制:1 秒 空间限制:131072 KB 分值: 0 难度:基础题 收藏 关注 回文串是指aba.abba.cccbccc.aaaa这种左右对称的字符串. 输入一个字 ...
- Codeforces 895C Square Subsets(状压DP 或 异或线性基)
题目链接 Square Subsets 这是白书原题啊 先考虑状压DP的做法 $2$到$70$总共$19$个质数,所以考虑状态压缩. 因为数据范围是$70$,那么我们统计出$2$到$70$的每个数的 ...
- 专访Nick McKeown:网络领域的游戏颠覆者
如果要找到一个过去10年在网络领域最热的词汇,那么非SDN(软件定义网络)莫属.在过去的十年间无论是学术机构还是标准组织,无论是电信巨擘还是互联网大厂都成其拥趸. 然而几乎每一件SDN的重大事件都离不 ...