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 106 #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++ "#"的作用和用法的更多相关文章
- serialVersionUID, ObjectInputStream与ObjectOutputStream类,Serializable接口,serialVersionUID的作用和用法
		ObjectInputStream与ObjectOutputStream类所读写的对象必须实现Serializable接口,对象中的transient和static类型成员变量不会被读取和写入 Ser ... 
- Oracle函数over(),rank()over()作用及用法--分区(分组)求和& 不连续/连续排名
		(1) 函数: over()的作用及用法: -- 分区(分组)求和. RANK ( ) OVER ( [query_partition_clause] order_by_clause )D ... 
- Linq中关键字的作用及用法
		Linq中关键字的作用及用法 1.All:确定序列中的所有元素是否都满足条件.如果源序列中的每个元素都通过指定谓词中的测试,或者序列为空,则为 true:否则为 false. Demo: 此示例使用 ... 
- JSP九大内置对象的作用和用法总结?
		JSP九大内置对象的作用和用法总结? 1.request对象javax.servlet.http.HttpServletRequest request对象代表了客户端的请求信息,主要用于接受通过HTT ... 
- (转载)MySQL数据类型中DECIMAL的作用和用法
		(转载)http://database.51cto.com/art/201005/201651.htm 在MySQL数据类型中,例如INT,FLOAT,DOUBLE,CHAR,DECIMAL等,它们都 ... 
- PreTranslateMessage作用和用法
		PreTranslateMessage作用和用法 PreTranslateMessage是消息在送给TranslateMessage函数之前被调用的,绝大多数本窗体的消息都要通过这里,比較经常使用, ... 
- ViewHolder的作用和用法
		一直都看别人用ViewHolder,自己也用过,却不知道它的作用是什么?但知道肯定很有用,而且现在android studio应该有直接生产Viewholder的插件, 不过博主我是个新手,就没尝试去 ... 
- Oracle分析函数及常用函数: over(),rank()over()作用及用法--分区(分组)求和& 不连续/连续排名
		(1) 函数: over()的作用及用法: -- 分区(分组)求和. sum() over( partition by column1 order by column2 )主要用来对某个字 ... 
- og标签对SEO的作用及用法
		meta property=og标签对SEO的作用及用法,如果你仔细观察会发现本站点<head>代码中有一段:"property="og:image"这段代码 ... 
- PHP  strip_tags() 函数的作用和用法
		strip_tags()函数可以轻松实现从字符串中去除 HTML 和 PHP 标记. 使用方法: trip_tags ( string $str [, string $allowable_tags ] ... 
随机推荐
- Foundation框架和文件操作
			NSString --实例化方法-------------- NSString *str = [[NSString alloc] init]; NSString *str = [[[NSString ... 
- 国内物联网平台初探(七) ——Ablecloud物联网自助开发和大数据云平台
			平台定位 面向IoT硬件厂商,提供设备联网与管理.远程查看控制.定制化云端功能开发.海量硬件数据存储与分析等基础设施,加速硬件实现联网智能化. 架构 服务 云端服务一体化开发引擎 业内独创一体化开发引 ... 
- eclipse中打字中文突然变成繁体
			eclipse中打字中文突然变成繁体 在用eclipse做android项目的时候,发现打出来的字全部是繁体,而且QQ等其他位置又是简体. 原因:eclipse的快捷点ctrl+alt+f(forma ... 
- python spark 求解最大 最小 平均 中位数
			rating_data_raw = sc.textFile("%s/ml-100k/u.data" % PATH) print rating_data_raw.first() nu ... 
- [WebServer] Linux下Apache与Tomcat整合的简单方法
			Apache与Tomcat比较联系 apache支持静态页,tomcat支持动态的,比如servlet等. 一般使用apache+tomcat的话,apache只是作为一个转发,对jsp的处理是由to ... 
- SQL注入原理解析以及举例1
			sql注入是指web应用程序对用户输入数据的合法性没有判断,导致攻击者可以构造不同的sql语句来实现对数据库的操作. sql注入漏洞产生满足条件: 1:用户能够控制数据的输入. 2:原本需要执行的代码 ... 
- shp系列(二)——利用C++进行shp文件的读(打开)
			1.各数据类型及其字节数 BYTE 1; char 1; short 2; int 4; double 8; 2.位序big和little及其转换 对于位序是big的 ... 
- 27. Remove Element[E]移除元素
			题目 Given an array nums and a value val, remove all instances of that value in-place and return the n ... 
- [hihocoder][Offer收割]编程练习赛43
			版本号排序 不知道什么傻逼原因,就是过不了 #pragma comment(linker, "/STACK:102400000,102400000") #include<st ... 
- P1732 活蹦乱跳的香穗子
			题目描述 香穗子在田野上调蘑菇!她跳啊跳,发现自己很无聊,于是她想了一个有趣的事情,每个格子最多只能经过1次,且每个格子都有其价值 跳的规则是这样的,香穗子可以向上下左右四个方向跳到相邻的格子,并且她 ... 
