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.类属性与对象属性 类中应该进存储所有对 ...
随机推荐
- 【Luogu】P3159交换棋子(超出我能力范围的费用流)
题目链接 明显超出我能力范围. 只放题解. 再放代码. #include<cstring> #include<algorithm> #include<cstdio> ...
- LOJ#2303. 「NOI2017」蚯蚓排队
$n \leq 200000$的$1 \leq a_i \leq 6$的蚯蚓,有三种操作:让一只队头蚯蚓接在一只队尾蚯蚓后面:让一队蚯蚓从某个蚯蚓后面断成两队:问:给个字符串,问他的..算了你们直接看 ...
- poj 1269 判断直线的位置关系
题目链接 题意 判断两条直线的位置关系,重合/平行/相交(求交点). 直线以其上两点的形式给出(点坐标为整点). 思路 写出直线的一般式方程(用\(gcd\)化为最简), 计算\(\begin{vma ...
- 内核的bootmem内存分配器【转】
转自:http://blog.csdn.net/zmxiangde_88/article/details/8041040 版权声明:本文为博主原创文章,未经博主允许不得转载. 在内核启动期间,伙伴系统 ...
- java string中indexOf()常用用法
Java中字符串中子串的查找共有四种方法,如下: 1.int indexOf(String str) :返回第一次出现的指定子字符串在此字符串中的索引. 2.int indexOf(String st ...
- java 四种方式实现字符流文件的拷贝对比
将D:\\应用软件\\vm.exe 拷贝到C:\\vm.exe 四种方法耗费时间对比 4>2>3>1 package Copy; import java.io.Buffere ...
- LeetCode OJ--Median of Two Sorted Arrays ***
http://oj.leetcode.com/problems/median-of-two-sorted-arrays/ 找两个有序数组的中位数,因为有序数组,并且复杂度要求O(lg(m+n))所以想 ...
- js-input file 文件上传(照片,视频,音频)
在此做一个笔记 <input type="file" accept="image/*" capture="camera"> &l ...
- CSS-滤镜 -webkit-filter
css滤镜属性,可以在元素呈现之前,为元素的渲染提供一些效果,如模糊.颜色转移之类的.滤镜常用于调整图像.背景.边框的渲染. 语法: webkit-filter: none | blur(px) | ...
- SPOJ 7001 VLATTICE【莫比乌斯反演】
题目链接: http://www.spoj.com/problems/VLATTICE/ 题意: 1≤x,y,z≤n,问有多少对(x,y,z)使得gcd(x,y,z)=1 分析: 欧拉搞不了了,我们用 ...