在前文中,我们曾看到,预处理指令的先执行性受到了原生字符串字面量的挑战。那么,这一指令的不符直觉之处还有哪些呢?这一次,峰子得寸进尺,进一步对 #include 指令进行战略试探。
首先,若将文件以词法记号为单位进行分割,存入多文件中,再向同一文件中做 #include ,会发生什么呢?
//test.cpp #include "include.txt" #include "using.txt" #include "outerfunc.txt" #include "mainfuncbegin.txt" #include "mainfunc.txt" #include "mainfuncend.txt"
//include.txt #include <iostream>
//using.txt using namespace std;
//outerfunc.txt void outerfunc() { cout << "From outerfunc():" <<endl; }
//mainfuncbegin.txt int main(int argc,char * argv[]) {
//mainfunc.txt cout << argv[0] << endl; outerfunc();
//mainfuncend.txt }
编译环境:TDM-GCC-32 4.7.2,Windows 7 旗舰版。
编译选项:
mingw32-g++ test.cpp -o test.exe -std=c++11
mingw32-g++ test.cpp -o test.exe
这个文件的编译是成功的。
运行结果:
prompt> dir /d
......
[.] mainfunc.txt outerfunc.txt using.txt
[..] mainfuncbegin.txt test.cpp
include.txt mainfuncend.txt test.exe
8 个文件 1,002,239 字节
2 个目录 9,725,964,288 可用字节
prompt> test
test
From outerfunc():
看起来,这样的分割是可以为编译器所接受的。
但是,是不是把文件无论怎么分割,都可以轻松通过编译呢?
//test.cpp #include "markstart.txt" #include "others.txt" #include "markend.txt" int main(){ return 0; }
//markstart.txt R"(
//others.txt Hello, world!
//markend.txt )"
编译环境:Windows 7 旗舰版,TDM-GCC-32 4.7.2编译选项和结果:
prompt> dir /d
......
[.] markend.txt others.txt test.cpp
[..] markstart.txt
4 个文件 116 字节
2 个目录 9,725,747,200 可用字节
prompt> mingw32-g++ test.cpp -o test.cpp -std=c++11
In file included from test.cpp:1:0:
markstart.txt:1:1: error: unterminated raw string
R"(
^
编译失败。
结合上个实验的结论不难明白,R"( 之后的内容都视为纯的字符串,不发挥语法功能,直到遇到 )" 为止。但是显然,它并不知道何时遇到或会不会遇到一个截止符,如果后面发现了新的 #include 指令,到底要不要展开,所以,编译器不可能允许上述代码通过编译。
峰子的一系列后续实验都指向这个结论:程序可以被分成多文件结构,当并且只有当每个文件中包含了完整的一个个词法单元(或称词法记号)时。
相关推荐
為了使讀者能夠活學活用,《從新手到高手C++全方位學習》針對重要的概念精心設計了438個實用範例,囊括大量經驗和技巧,即使已從事C++工作多年的朋友,也能從中汲取新的養料。 《從新手到高手C++全方位學習》適合於...
2.1.2 #include指令——头文件 37 2.1.3 命名空间和using声明 37 2.1.4 main()函数 38 2.1.5 程序语句 38 2.1.6 空白 40 2.1.7 语句块 41 2.1.8 自动生成的控制台程序 41 2.2 定义变量 42 2.2.1 ...
1、预处理器——#include将iostream文件内容添加到程序中。老式C头文件保留了扩展名.h,而C++头文件没有扩展名。 (有些C头文件被转换为C++头文件,去掉扩展名,并在前面加c,如cmath) 2、名称空间——相当于Java中...
2.1.2 #include指令——头文件 2.1.3 命名空间和using声明 2.1.4 main()函数 2.1.5 程序语句 2.1.6 空白 2.1.7 语句块 2.1.8 自动生成的控制台程序 2.2 定义变量 2.2.1 命名变量 2.2.2 C++中的关键字 2.2.3 声明变量...
2.1.2 #include指令——头文件 2.1.3 命名空间和using声明 2.1.4 main()函数 2.1.5 程序语句 2.1.6 空白 2.1.7 语句块 2.1.8 自动生成的控制台程序 2.2 定义变量 2.2.1 命名变量 2.2.2 C++中的关键字 2.2.3 声明变量...
17.2 预处理指令#include 17.3 预处理指令#define:符号常量 17.4 预处理指令#define:宏 17.5 条件编译 17.6 预处理指令#error和#pragma 17.7 运算符#和## 17.8 行号 17.9 预定义的符号常量 17.10 断言(宏...
2.1.2 #include指令——头文件 2.1.3 命名空间和using声明 2.1.4 main()函数 2.1.5 程序语句 2.1.6 空白 2.1.7 语句块 2.1.8 自动生成的控制台程序 2.2 定义变量 2.2.1 命名变量 2.2.2 C++中的关键字 2.2.3 声明变量...
17.2 预处理指令#include 17.3 预处理指令#define:符号常量 17.4 预处理指令#define:宏 17.5 条件编译 17.6 预处理指令#error和#pragma 17.7 运算符#和## 17.8 行号 17.9 预定义的符号常量 17.10 断言(宏...
2.1.2 #include指令——头文件 2.1.3 命名空间和using声明 2.1.4 main()函数 2.1.5 程序语句 2.1.6 空白 2.1.7 语句块 2.1.8 自动生成的控制台程序 2.2 定义变量 2.2.1 命名变量 2.2.2 C++中的关键字 2.2.3 声明变量...
2.1.2 #include指令——头文件 2.1.3 命名空间和using声明 2.1.4 main()函数 2.1.5 程序语句 2.1.6 空白 2.1.7 语句块 2.1.8 自动生成的控制台程序 2.2 定义变量 2.2.1 命名变量 2.2.2 C++中的关键字 2.2.3 声明变量...
2.1.2 #include指令——头文件 2.1.3 命名空间和using声明 2.1.4 main()函数 2.1.5 程序语句 2.1.6 空白 2.1.7 语句块 2.1.8 自动生成的控制台程序 2.2 定义变量 2.2.1 命名变量 2.2.2 C++中的关键字 2.2.3 声明变量...
1.1 Microsoft.NET——一场新的革命.4 1.2 .NET 与 C#.6 1.3 C#语言的特点.8 1.4 小 结 .11 第二章 运行环境 全面了解.NET.12 2.1 .NET 结构.12 2.2 公用语言运行时环境与公用语言规范.13 2.3 开 发 ...
5.4 可以用#include指令包含类型名不是“.h”的文件吗? 5.5 用#define指令说明常量有什么好处? 5.6 用enum关键字说明常量有什么好处? 5.7 与用#define指令说明常量相比,用enum关键字说明常量有什么好处? ...
可我找不到任何方法来声明这样的函数——感觉我需要一个返回指针的函数,返回的指针指向的又是返回指针的函数……,如此往复,以至无穷。 12 数组大小 13 1.23 能否声明和传入数组大小一致的局部数组,或者由...
可我找不到任何方法来声明这样的函数——感觉我需要一个返回指针的函数,返回的指针指向的又是返回指针的函数……,如此往复,以至无穷。 数组大小 1.23 能否声明和传入数组大小一致的局部数组,或者由其他参数...
5.4. 可以用#include指令包含类型名不是".h"的文件吗? 80 5.5. 用#define指令说明常量有什么好处? 80 5.6. 用enum关键字说明常量有什么好处? 81 5.7. 与用#define指令说明常量相比,用enum关键字说明常量有什么好处?...