C++预处理器

预处理器是一些指令,指示表一起在实际编译之前所需要完成的预处理。

所有的预处理器指令都是以井号(#)开头,只有空格字符可以出现在预指令处理之前。预处理指令不是C++语句,所以他们不会以分号(;)结尾。

 

#define预处理

#define预处理指令用于创建符号常量。该符号常量通常称之为宏,指令的一般行为为

#define macro-name replacement-text

当这行代码出现在一个文件中,在该文件中后续出现的所有宏都会在程序编译之前被替换成成replacement-text。

/***
define.cpp
***/
#include<iostream>
using namespace std;#define PI 3.14159int main()
{cout << "Value of PI :" << PI << endl;return 0;
}

使用-E选项进行编译,并把结果重定向到define.p 现在查看一下相关信息:

exbot@ubuntu:~/wangqinghe/C++/20190816$ gcc -E define.cpp > define.p

条件编译

有几个指令可以用来有选择地对部分程序源代码进行编译,这个过程称之为条件编译。

条件预处理器地结构与if选择结构很像。

#ifdef NULL#define NULL 0
#denif

在调试时进行编译,调试开关可以使用一个宏来实现

#ifdef DEBUGcerr << “Variable x = ” << x << endl;
#endif

如果在指令 #ifdef DEBUF 之前定义了符号常量,则会对程序中cerr语句进行编译。可以使用 #if 0 语句注释掉程序的一部分。

#if 0 不进行编译的代码
#endif

实例:

/***
ifdef.cpp
***/
#include<iostream>
using namespace std;
#define DEBUG#define MIN(a,b) (((a) < (b)) ? a : b)int main()
{int i,j;i = 100;j = 20;
#ifdef DEBUGcerr << "Trace: Inside main function" << endl;
#endif#if 0cout << "MKSTR(HELLO C++)" << endl;
#endifcout << "The minimum is " << MIN(i,j) << endl;#ifdef DEBUGcerr << "Trace: Comint out of main function" << endl;
#endifreturn 0;
}

运行结果:

exbot@ubuntu:~/wangqinghe/C++/20190816$ g++ ifdef.cpp -o ifdef

exbot@ubuntu:~/wangqinghe/C++/20190816$ ./ifdef

Trace: Inside main function

The minimum is 20

Trace: Comint out of main function

#和##运算符

#和##预处理运算符在C++和ANSI/ISO C中都是可用的

#运算符会把repalcement-text令牌转换成引号引起来的字符串

/***
pound.cpp
***/
#include<iostream>
using namespace std;#define MKSTR(x) #xint main()
{cout << MKSTR(HELLO C++) << endl;return 0;
}

运行结果:

exbot@ubuntu:~/wangqinghe/C++/20190816$ g++ pound.cpp -o pound

exbot@ubuntu:~/wangqinghe/C++/20190816$ ./pound

HELLO C++

 

C++预处理器把下面这行

cout << MKSTR(HELLO C++) << endl;

转化成了:

cout << “HELLO C++” << endl;

##运算符用于连接两个令牌

#define CONCAT(x,y) x ## y

当CONCAT出现在程序中,他的参数机会被连接起来,并用来取代宏,程序中CONCAT(HELLO C++)会被替换成“HELLO C++”如下图:

/***
concat.cpp
***/
#include<iostream>
using namespace std;#define concat(a,b) a##b
int main()
{int xy = 100;cout << concat(x,y) << endl;return 0;
}

运行结果:

exbot@ubuntu:~/wangqinghe/C++/20190816$ g++ concat.cpp -o concat

exbot@ubuntu:~/wangqinghe/C++/20190816$ ./concat

100

 

C++预处理器把下面这行:

cout << concat(x,y) << endl;

转化成了:

cout << xy;

C++中的预定义宏

 

C++提供了下表所示的一些预定义宏:

描述

__LINE__

这会在编译时包含当前行号

__FILE__

这会在编译时包含当前文件名

__DATA__

这会包含一个形式为month/day/year的字符串,它表示把源文件转换成目标代码的日期

__TIME__

这会包含一个形式为hour:minute:second的字符串,它表示程序被编译的时间

 

实例:

/***
macro.cpp
***/
#include<iostream>
using namespace std;int main()
{cout << "Value of __LINE__ :" << __LINE__ << endl;cout << "Value of __FILE__ :" << __FILE__ << endl;cout << "Value of __DATE__ :" << __DATE__ << endl;cout << "Value of __TIME__ :" << __TIME__ << endl;return 0;
}

运行结果:

exbot@ubuntu:~/wangqinghe/C++/20190816$ g++ macro.cpp -o macro

exbot@ubuntu:~/wangqinghe/C++/20190816$ ./macro

Value of __LINE__ :6

Value of __FILE__ :macro.cpp

Value of __DATE__ :Aug 16 2019

Value of __TIME__ :14:06:20

# 和 ## 运算符

# 字符串化的意思,出现在宏定义中的#是把跟在后面的参数转换成一个字符串。

当用作字符串化操作时,# 的主要作用是将宏参数不经扩展地转换成字符串常量。

 宏定义参数的左右两边的空格会被忽略,参数的各个 Token 之间的多个空格会被转换成一个空格。

 宏定义参数中含有需要特殊含义字符如"或\时,它们前面会自动被加上转义字符 \。

## 连接符号,把参数连在一起。

将多个 Token 连接成一个 Token。要点:

 

 它不能是宏定义中的第一个或最后一个 Token。

 前后的空格可有可无。

 

转载于:https://www.cnblogs.com/wanghao-boke/p/11363571.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/384869.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Python变量类型

变量存储在内存中的值&#xff0c;这就意味着在创建变量时会在内存开辟一个空间。 基于变量的数据类型&#xff0c;解析器会分配指定内存&#xff0c;并决定什么数据可以被存储在内存中。 因此变量可以指定不同的数据类型&#xff0c;这些变量可以存储整数、小数、或字符。 变量…

Python3字符串

字符串是Python中最常用的数据类型&#xff0c;可以使用单引号或双引号来创建字符串 创建字符串很简单&#xff0c;为变量分配一个值即可。 val1 ‘hello world’ var2 “Runoob” Python访问字符串的值 Python不支持单字符类型&#xff0c;单字符在Python中也是作为 一个字符…

服务器客户端编程

server 下面通过最简单的客户端/服务器程序的实例来学习socket API。 server.c的作用是从客户端读字符&#xff0c;然后将每个字符转换为大写并回送给客户端。 #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #incl…

Python3元组

Python的元组与列表相似&#xff0c;不同之处在于元组的元素不能修改 元组使用小括号&#xff0c;列表使用方括号 元组创建很简单&#xff0c;只需要在括号中添加元素&#xff0c;并使用逗号隔开即可。 创建空元组 tup1 (); tup2 (1,) 元组只包含一个元素时&#xff0c;需要在…

Python3字典

字典是另一种可变容器模型&#xff0c;可存储任意类型的对象。 字典的每个键值(key>value)对用冒号分隔&#xff0c;每个对之间用逗号分隔&#xff0c;整个字典包括在花括号里&#xff0c;格式如下 d {key1 : value,key2 : value2} 键必须是唯一&#xff0c;但值则不必。 值…

多进程服务器

注意&#xff1a;包含了“wrap.c” 和“wrap.h”文件在上篇博客中 /*** server.c ***/ #include<stdio.h> #include<string.h> #include<netinet/in.h> #include<arpa/inet.h> #include<signal.h> #include<sys/wait.h> #include<ctype…

Python3集合

集合&#xff08;set&#xff09;是一个无序的不重复元素序列。 可以使用大括号{ } 或set&#xff08;&#xff09;函数来创建集合&#xff0c;注意&#xff1a;创建一个空集合必须用set(),{ }是用来创建一个空字典的。 创建格式&#xff1a; param {value01,value02,…} set(…

Python3循环

Python中while语句的一般形式&#xff1a; while 判断条件: 语句 同样需要注意冒号和缩进&#xff0c;另外在Python中没有do…while循环 下面的实例计算1到100总和 ##calc.py n 100sum 0 counter 1 while counter < n:sum sum countercounter 1print("total from…

Python3迭代器和生成器

迭代器 迭代是Python最强大的功能之一&#xff0c;是访问元素集合的一种方法。 迭代器是一个可以记住遍历的位置的对象。 迭代器对象从集合的第一个元素开始访问&#xff0c;直到所有的元素被访问完结束&#xff0c;迭代器只能向前不会后退。 迭代器有两个基本方法&#xff0c;…

Python3函数

函数是组织好的&#xff0c;可重复使用的&#xff0c;用来实现单一&#xff0c;或相关功能的代码段。 函数能提高应用的模块性&#xff0c;和代码的重复使用率。 定义一个函数 可以定义一个由自己想要功能的函数&#xff0c;以下是简单规则&#xff1a; l 函数代码块是以def关…

epoll函数

epoll是Linux下多路复用IO接口select/poll的增强版本&#xff0c;它能显著提高程序在大量并发连接中只有少量活跃的情况下的系统CPU利用率&#xff0c;因为它会复用文件描述符集合来传递结果而不用迫使开发者每次等待事件之前都必须重新准备要被侦听的文件描述符集合&#xff0…

Python3数据结构

列表&#xff1a; Python列表是可变的&#xff0c;这是它区别于字符串数组和元组的最重要的特点。列表可以修改&#xff0c;而字符串和元组不能。 以下是Python中列表的描述方法&#xff1a; 方法 描述 list.append(x) 将元素添加到列表结尾 list.extend(L) 通过添加指定列…

Python3输入输出

Python两种输出值的方式&#xff0c;表达式语句和print()函数。 第三种方式是使用文件对象的write()方法&#xff0c;标准输出文件可以用sys.stdout的引用。 如果你希望输出的形式更加多样&#xff0c;可以使用str.fomat()函数来格式化输出值。 如果你希望将输出的值转化成字符…

Python3正则表达式

正则表达式是一个特殊的字符序列&#xff0c;他能帮助你方便的检查一个字符串是否与某种模式匹配。re.match函数 re.match尝试从字符串的起始位置匹配一个模式&#xff0c;如果不是起始位置匹配成功的话&#xff0c;match()就返回一个none。 函数语法&#xff1a; re.match(pat…

signal()函数

函数原型 void (*signal(int sig,void(*func)(int)))(int); 指定使用sig指定的信号编号处理信号的方法。参数func指定程序可以处理信号的三种方式之一&#xff1a; l 默认处理(SIG_DFL)&#xff1a; 信号由该特定信号的默认动作处理l 忽略信号&#xff08;SIG_IGN&a…

【C++学习之路】第一章——C++核心方法总论

1 C核心方法总论 1.1 核心思想 通过实际项目来学习编程&#xff0c;更高效掌握编程规则&#xff0c;以及明白各种语法规则的实际应用。 实验思想&#xff1a;任何C的参考资料都不可能覆盖你遇到的所有问题&#xff0c;这个时候&#xff0c;最好的办法就是&#xff0c;编辑代…

【学会如何学习系列】从婴儿到大学——学习的本质从未改变过

从婴儿到大学——学习的本质从未改变过 从我们出生一直到现在&#xff0c;其实&#xff0c;学习的本质从来都没有改变过&#xff0c;并且&#xff0c;婴儿时期的我们&#xff0c;是学习能力最强的时候&#xff0c;随着我们不断长大&#xff0c;外界的诱惑越来越多&#xff0c;…

【Verilog HDL学习之路】第二章 Verilog HDL的设计方法学——层次建模

2 Verilog HDL的设计方法学——层次建模 重要的思想&#xff1a; 在语文教学中&#xff0c;应该先掌握核心方法论&#xff0c;再用正确的方法论去做题目&#xff0c;这样能够逐渐加深对于方法论的理解&#xff0c;做题的速度和准确率也会越来越高。在Verilog HDL中&#xff0c…

【Verilog HDL】第四章 模块的端口连接规则——污水处理模型

先放上连接规则的简图&#xff0c;再详细解释 1. 构建模型——污水处理之流水模型 我们先将上述结构构件一个简单模型&#xff0c;以帮助我们理解。 污水&#xff1a;输入数据净水&#xff1a;输出数据双向数据暂不讨论&#xff0c;取输入和输出的交集即可污水处理厂&…

【Verilog HDL】从逻辑电路图到门级建模——人工翻译的方法论

从左到右&#xff0c;从上到下 先搞定缓冲/非门&#xff0c;再写与/或门 1. 实例解读 先以四选一数据选择器进行说明 对于数字逻辑的部分不再说明&#xff0c;直接进行逻辑电路图到Verilog门级建模的人工翻译过程的描述。 1.1 端口和线网分析 确定输入/输出端口 输入端口 …