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.类属性与对象属性 类中应该进存储所有对 ...
随机推荐
- html 文本标签
文本格式化标签 标签 描述 <b> 定义粗体文本. <big> 定义大号字. <em> 定义着重文字. <i> 定义斜体字. <small> ...
- [图论训练]1143: [CTSC2008]祭祀river 二分图匹配
Description 在遥远的东方,有一个神秘的民族,自称Y族.他们世代居住在 水面上,奉龙王为神.每逢重大庆典, Y族都会在水面上举办盛大的祭祀活动.我们可以把Y族居住地水系看成一个由岔口和河道组 ...
- C/C++ XMPP/Jabber 客户端类库对比/点评 (转)
原文转自 http://blog.csdn.net/educast/article/details/31359835 1.gloox Ans. 老牌库,推荐 gloox是一个稳定功能完整的XMPP客户 ...
- ROS学习网址【原创】
ROS学习网址 http://www.ros.org/ http://www.ros.org/news/book/ http://wiki.ros.org/ http://blog.exbot.net ...
- Cmder 快捷键
1, Cmder常用快捷键 利用Tab,自动路径补全: 利用Ctrl+T建立新页签:利用Ctrl+W关闭页签; 利用Ctrl+Tab切换页签; Alt+F4:关闭所有页签 Alt+Shift+1:开启 ...
- SD-WAN用户实践分享:老网工趟出的SD-WAN成功路
在这个离开“人大物云”(人-人工智能.大-大数据.物-物联网.云-云计算)话题都张不开嘴的年代,在这个在咖啡店谈生意都不好意思低于1个亿的年代,反思我的老本行——网络,正在以一种全新的.更加重要的姿态 ...
- TCP server和client的一些测试
一.TCP server和client测试 socket设置 测试项/测试情景 send recv 测 server block client bloc ...
- android 什么时候call super.onDestory()等
Methods you override that are part of component creation (onCreate(), onStart(), onResume(), etc.), ...
- codeforces A. Wrong Subtraction
A. Wrong Subtraction time limit per test 1 second memory limit per test 256 megabytes input standard ...
- ARM 浮点运算
转载: http://www.embedu.org/Column/Column821.htm http://blog.sina.com.cn/s/blog_602f87700100r5xe.html ...