2017-10-15 188 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 

順便說一下,預處理器的工作原理,包含每個翻譯單元的順序非常重要。

相關問題