另外,还发现一个定位编译错误的简单方法。比如在上述情况下,编译器爆出的错误定位到了iostream里边,但肯定不是iostream文件里边的代码存在错误,那可是系统文件。
这时,使用#pragma message("字符串") 可以方便的辅助定位。比如我在一个文件里,有以下包含关系:
#include "A.h"
#include "B.h"
...
那么将#pragma message() 放到两行中间,即:
#include "A.h"
#pragma message("...")
#include "B.h"
...
则编译器在编译当前文件时,在编译#include "B.h"之前,会先输出message中指定的字符串。如果编译错误在B.h中,则编译器报错内容将在message内容后出现。否则在B.h之前出现。用这个方法就可以确定错误出现的范围,并可以结合二分法进一步缩小范围。
11) 1i64 非法符号定义
使用场景:
将Windows上的代码迁移到Mac上,遇到1i64无法识别,被认为非法变量。使用方法是:
1i64<<(2*i)
其中i64是一个后缀,1表示一个数值。
解决方法:
首先,1i64是Windows操作系统为保证64位和32位程序的安全性而定义的一个值。根据C ++标准有int类型。 在64位Microsoft编译器int有sizeof = 4个字节,这意味着int是32位变量。 1i64的类型是__int64。
使用移位运算符时,结果的类型与左操作数的类型相同。 这意味着转换1你会得到32位的结果。微软编译器认为它可能不是你所期望的(在64位平台上),并给你警告信息。当你使用1i64的结果在两个平台上都是64位的。 j和0将隐式转换为64位。 所以整个表达式将以64位变量计算,结果将是bool。所以用1i64在Win32和Win64上都是安全的。
但当需要将代码移植到非Windows平台的操作系统时,1i64成了一个不能识别的符号,编译时便报上述错误。根据微软官方文档,i64与LL均是用于定义一个64位的整型常量。
而LL在Unix上有定义,因此替换i64为LL。