错误 C2156: pragma must be outside function - 为啥会在这种情况下发生?

Posted

技术标签:

【中文标题】错误 C2156: pragma must be outside function - 为啥会在这种情况下发生?【英文标题】:error C2156: pragma must be outside function - why is it happening in this case?错误 C2156: pragma must be outside function - 为什么会在这种情况下发生? 【发布时间】:2017-10-15 19:11:22 【问题描述】:

给出这组 4 个文件:

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"

当我尝试使用 Visual Studio 2015 编译器 cl -c file2.cpp 编译 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 行,文件将被编译好。谁能解释一下这里发生了什么?因为我不明白,docs 没有解决任何问题。

【问题讨论】:

了解what the macro actually does 并认为N 是常用的标识符。 我最好的猜测是您的宏定义破坏了标题um/winnt.h 中的某些内容,这显然包含在windows.h 中。在这种情况下,翻转 file2.cpp 中 #include 指令的顺序也应该可以解决问题。 const int 可以使用宏时,为什么要使用宏?为什么它是全球性的?为什么它没有一个比“N”更好、更具描述性的名字? 【参考方案1】:

类对象宏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;

(请注意,在 C 中您可能会使用 static const,因为 const 的默认链接是外部链接)

【讨论】:

谢谢,我不知道windows.h 文件中会显示该宏【参考方案2】:

你不应该用像“N”这样的短名称来定义宏。几乎 100% 的可能性,这将与您之后包含的标头中的某些内容发生冲突,例如 Windows.h:如果在其中某处提到“N”,则预处理器会将其替换为 666,可能会使程序格式错误或导致其他难以调试的奇怪预处理器效果,并且对于您的头文件的任何用户(包括您自己)来说都是一场噩梦。

无论如何,如果你坚持这样做(你真的不应该这样做,尤其是在头文件中),请确保在包含任何头文件后#define N:

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

这将解决

#include <windows.h>
#define N666

根据预处理器的工作方式,每个翻译单元包含的顺序很重要。

【讨论】:

以上是关于错误 C2156: pragma must be outside function - 为啥会在这种情况下发生?的主要内容,如果未能解决你的问题,请参考以下文章

python TypeError: must be str, not bytes错误

django1.11 启动错误:Generator expression must be parenthesized

如何解决错误 Salt must be 8 bytes long

django1.11 启动错误:Generator expression must be parenthesized

Python错误TypeError: write() argument must be str, not bytes

Unicode-objects must be encoded before hashing 错误解决办法