错误C2156:pragma必须在函数之外 - 为什么在这种情况下会发生?

时间:2017-10-15 19:11:22

标签: c++ c visual-studio pragma

给出这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没有解决任何问题。

2 个答案:

答案 0 :(得分: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;

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

答案 1 :(得分:1)

您不应该使用诸如&#34; N&#34;这样的短名称来定义宏。几乎100%的概率,这将与之后包含的标题内的某些内容发生冲突,如Windows.h:如果在其中的某个地方,则会出现&#34; N&#34;提到,预处理器将用666替换它,可能使程序格式不正确或导致难以调试的其他奇怪的预处理器效果,并且对于头文件的任何用户来说都是一场噩梦,包括你自己。

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

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

将解析为

#include <windows.h>
#define N666

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