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...elseif...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.
时间: 2024-10-08 22:02:34

C++ &quot;#&quot;的作用和使用方法的相关文章

node app.js不起作用的解决方法

In Express 3.0, you normally would use app.configure() (or app.use() ) to set up the required middleware you need. Those middleware you specified are bundled together with Express 3.0. e.g. var express = require('express'); var routes = require('./ro

JAVA 注解的几大作用及使用方法详解

JAVA 注解的几大作用及使用方法详解 (2013-01-22 15:13:04) 转载▼ 标签: java 注解 杂谈 分类: Java java 注解,从名字上看是注释,解释.但功能却不仅仅是注释那么简单.注解(Annotation) 为我们在代码中添加信息提供了一种形式化的方法,是我们可以在稍后 某个时刻方便地使用这些数据(通过 解析注解 来使用这些数据),常见的作用有以下几种: 1.生成文档.这是最常见的,也是java 最早提供的注解.常用的有@see @param @return 等:

PHP trim()函数的作用和使用方法

PHP trim()函数一般是用来去除字符串首尾处的空白字符(或者其他字符),一般在用在服务端对接收的用户数据进行处理,以免把用户误输入的空格存储到数据库,下次对比数据时候出错. 该函数有两个参数,第二个可以为空,格式如下: trim ( string $str [, string $character_mask = ” \t\n\r\0\x0B” ] ): $str 为需要处理的字符串,如果$character_mask不为空,只会清楚$character_mask上写的要求清楚的字符:如果第

serialVersionUID的作用以及设置方法(转)

声明:本篇文章是转载的 http://blog.csdn.net/kakaxi_77/article/details/8129070 http://snowlotus.iteye.com/blog/247129 java文件中serialVersionUID的作用 http://blog.csdn.net/hulefei29/article/details/2823221 serialVersionUID的作用 http://www.blogjava.net/invisibletank/arch

子网掩码的作用和设置方法

子网掩码是每个网管必须要掌握的基础知识,只有掌握它,才能够真正理解TCP/IP协议的设置.以下我们就来深入浅出地讲解什么是子网掩码. IP地址的结构 要想理解什么是子网掩码,就不能不了解IP地址的构成.互联网是由许多小型网络构成的,每个网络上都有许多主机,这样便构成了一个有层次的结构.IP地址在设计时就考虑到地址分配的层次特点,将每个IP地址都分割成网络号和主机号两部分,以便于IP地址的寻址操作. IP地址的网络号和主机号各是多少位呢?如果不指定,就不知道哪些位是网络号.哪些是主机号,这就需要通

js split str.split(&amp;quot; &amp;quot;); split使用方法 在某处截字符串

<script language="javascript">    str="2,2,3,5,6,6"; //这是一字符串var strs= new Array(); //定义一数组 strs=str.split(","); //字符切割      for (i=0;i<strs.length ;i++ )        {            document.write(strs[i]+"<br/>&

关于使用Github,gitignore不起作用的解决方法

直接上解决方法: 1 2 3 git rm -r --cached . git add . git commit -m 'update .gitignore' 解释: .gitignore文件,具体的规则一搜就有.我在使用Git的过程中,明明写好了规则,但问题不起作用,每次还是重复提交,无法忍受.其实这个文件里的规则对已经追踪的文件是没有效果的.所以我们需要使用rm命令清除一下相关的缓存内容.这样文件将以未追踪的形式出现.然后再重新添加提交一下,.gitignore文件里的规则就可以起作用了.

[转]什么是C++虚函数、虚函数的作用和使用方法

我们知道,在同一类中是不能定义两个名字相同.参数个数和类型都相同的函数的,否则就是“重复定义”.但是在类的继承层次结构中,在不同的层次中可以出现名字相同.参数个数和类型都相同而功能不同的函数.例如在例12.1(具体代码请查看:C++多态性的一个典型例子)程序中,在Circle类中定义了 area函数,在Circle类的派生类Cylinder中也定义了一个area函数.这两个函数不仅名字相同,而且参数个数相同(均为0),但功能不同,函数体是不同的.前者的作用是求圆面积,后者的作用是求圆柱体的表面积

gridview 外嵌套HorizontalScrollView 横向滑动后setselection(position)不起作用的解决方法

gridview滑动不起作用 就用外层horizontalscrollview 的滑动方法吧,只需要计算一下需要滑动的横向距离,代码如下: hsv.smoothScrollTo(vStepsHorizonListview.getChildAt(position) .getWidth() * position, 0); 版权声明:本文为博主原创文章,未经博主允许不得转载.