今天写代码的时候遇到了这个错误,想跟大家分享下。
这是一个神奇的编译错误。报错的地方打开可能完全看不到哪里有问题,甚至你上网找也不好找到具体出错的原因。
看报错内容,应该是class前缺少一些东西导致他认为出错了,比如函数定义最后少了一个分号之类的。但是打开出错的文件一看,可能就一个include,然后就是class了,根本看不出少了什么东西。这里,了解c编译流程的同学就知道了,include头文件,实际上在预处理阶段,就是把文件直接展开,然后根据宏进行各种替换而已。所以很有可能,是头文件里面,哪里出错了,然后在这个文件里include,被展开,之后编译报错。
此时怎么办呢?难道一个个头文件翻过去?如果你一边写一遍编译,那就翻一下记录就好。但是如果不是呢?怎么办?甚至这个可能是一个开源项目,别人写的,你不熟,怎么办?要知道,include进来的头文件,可能也include了头文件,没有人保证错误就是出在直接include的那个文件。比如今天我遇到的错误,就是在好几层外面include进来的文件有一个错误导致了问题。
由于这个错误是编译错误,不是链接错误,所以实际上我们只要知道经过预处理的文件怎么样,就知道怎么处理了。gcc输出预处理结果的选项为-E
这个时候,你只要把原本用来编译这个文件的gcc命令,一般这个阶段,如果使用的是makefile,输出的是-o x.o 目标文件,只需要把这个-o x.o替换成-E,然后重定向到一个文件即可。
比如原本编译命令为:
gcc a.cpp -I./ -o a.o
这里把当前目录加入到头文件的搜索路径,然后编译a.cpp,输出a.o,obj文件。
我们只需要用
gcc a.cpp -I./ -E > output.cpp
即可得到预编译之后的结果。然后就能很直观的看到,具体哪里出错了。
一般来说,常见的,影响预编译的选项包括:
- -I./ 头文件搜索路径
- -DNUM=1 宏定义
- -std=c++11 c标准定义
- mac的话可能会有-f frameword之类的选项,导入框架
- 内核或者嵌入式,或者交叉编译之类的,会有-nostdinc 或者 -nostdinc++ ,禁止本地标准头文件引入(需要使用目标平台的头文件)。
- 还有一些头文件搜索路径的环境变量,比如C_INCLUDE_PATH和CPLUS_INCLUDE_PATH等。
当然还有各种Error选项和Warning选项。非常非常特殊的项目,还会有取消宏定义之类的参数,这里不细究,一般就是这些了。所以使用-E参数的时候要保证这些内容跟make的时候一样,即可拉。