2017-10-15 189 views
0

给出这组4个文件:错误C2156:杂注必须在函数之外 - 为什么在这种情况下发生?

file1.h:

#pragma once 
#include <windows.h> 

file1.cpp:

#include "file1.h" 

file2.h:

#pragma once 

#define N 666 

file2.cpp:

#include "file2.h" 
#include "file1.h" 

当我尝试编译file2.cpp与Visual Studio 2015年编译器cl -c file2.cpp我会得到一堆错误:

Microsoft (R) C/C++ Optimizing Compiler Version 19.00.24215.1 for x86 
Copyright (C) Microsoft Corporation. All rights reserved. 

file2.cpp 
C:\Program Files (x86)\Windows Kits\8.1\include\\um\winnt.h(1179): error C2059: syntax error: 'constant' 
C:\Program Files (x86)\Windows Kits\8.1\include\\um\winnt.h(2149): error C2598: linkage specification must be at global scope 
C:\Program Files (x86)\Windows Kits\8.1\include\\um\winnt.h(4807): error C2598: linkage specification must be at global scope 
C:\Program Files (x86)\Windows Kits\8.1\include\\um\winnt.h(4859): error C2156: pragma must be outside function 
C:\Program Files (x86)\Windows Kits\8.1\include\\um\winnt.h(4991): error C2598: linkage specification must be at global scope 
C:\Program Files (x86)\Windows Kits\8.1\include\\um\winnt.h(5050): error C2156: pragma must be outside function 
C:\Program Files (x86)\Windows Kits\8.1\include\\um\winnt.h(5051): error C2156: pragma must be outside function 
C:\Program Files (x86)\Windows Kits\8.1\include\\um\winnt.h(5052): error C2156: pragma must be outside function 
C:\Program Files (x86)\Windows Kits\8.1\include\\um\winnt.h(5053): error C2156: pragma must be outside function 
C:\Program Files (x86)\Windows Kits\8.1\include\\um\winnt.h(5054): error C2156: pragma must be outside function 
C:\Program Files (x86)\Windows Kits\8.1\include\\um\winnt.h(5055): error C2156: pragma must be outside function 
C:\Program Files (x86)\Windows Kits\8.1\include\\um\winnt.h(5078): error C2156: pragma must be outside function 
C:\Program Files (x86)\Windows Kits\8.1\include\\um\winnt.h(5079): error C2156: pragma must be outside function 
C:\Program Files (x86)\Windows Kits\8.1\include\\um\winnt.h(5134): error C2156: pragma must be outside function 
C:\Program Files (x86)\Windows Kits\8.1\include\\um\winnt.h(5135): error C2156: pragma must be outside function 
C:\Program Files (x86)\Windows Kits\8.1\include\\um\winnt.h(5136): error C2156: pragma must be outside function 
C:\Program Files (x86)\Windows Kits\8.1\include\\um\winnt.h(5137): error C2156: pragma must be outside function 
C:\Program Files (x86)\Windows Kits\8.1\include\\um\winnt.h(15420): error C2059: syntax error: 'constant' 
C:\Program Files (x86)\Windows Kits\8.1\include\\um\winnt.h(15420): error C2238: unexpected token(s) preceding ';' 
C:\Program Files (x86)\Windows Kits\8.1\include\\um\winnt.h(15439): error C2059: syntax error: 'constant' 
C:\Program Files (x86)\Windows Kits\8.1\include\\um\winnt.h(15439): error C2238: unexpected token(s) preceding ';' 

但如果我评论的线#define N 666该文件将被编译OK。任何人都可以解释我在这里发生了什么?因为我不明白,docs没有解决任何问题。

+3

理解[什么宏实际上](http://en.cppreference.com/w/cpp/preprocessor/replace),并认为'N'是一个常用的标识符。 – chris

+0

我最好的猜测是你的宏定义会在头文件'um/winnt.h'中打开某些东西,这显然是由'windows.h'包含的。在这种情况下,翻转file2.cpp中的'#include'指令的顺序也应该解决问题。 –

+0

为什么在'const int'会做什么时使用宏?为什么它是全球性的?为什么它没有比“N”更好,更具描述性的名称? –

回答

2

与对象相似的宏Nwindows.h相冲突,其中包括winnt.h

例如:

extern "C++" // templates cannot be declared to have 'C' linkage 
template <typename T, size_t N> 
char (*RtlpNumberOf(UNALIGNED T (&)[N]))[N]; 

我建议避免使用宏时,您可以。在C和C++,你可以考虑用const对象来代替宏定义:

const int N = 666; 

(注意,你可能会使用static const C,因为const默认连接外部)

+0

谢谢,我不知道宏将在'windows.h'文件中可见 – BPL

1

你不应该用像“N”这样的短名称来定义宏。几乎有100%的可能性,这将与事后包含的头文件中的内容相冲突,例如Windows.h:如果提到了“N”,则预处理器会将其替换为666,可能使程序不合格或导致难以调试的其他奇怪的预处理器效果,以及头文件的任何用户(包括您自己)的噩梦。

无论如何,如果你坚持这样做(你真的不应该,尤其是在头文件),请确保您#定义ň包括任何头之后:

#include "file1.h" 
#include "file2.h" 

将解析为

#include <windows.h> 
#define N666 

顺便说一下,预处理器的工作原理,包含每个翻译单元的顺序非常重要。

相关问题