error C2156: pragma must be outside function - 为什么会发生在这种情况下?

error C2156: pragma must be outside function - why is it happening in this case?

给出这组 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.1\include\um\winnt.h(1179): error C2059: syntax error: 'constant'
C:\Program Files (x86)\Windows Kits.1\include\um\winnt.h(2149): error C2598: linkage specification must be at global scope
C:\Program Files (x86)\Windows Kits.1\include\um\winnt.h(4807): error C2598: linkage specification must be at global scope
C:\Program Files (x86)\Windows Kits.1\include\um\winnt.h(4859): error C2156: pragma must be outside function
C:\Program Files (x86)\Windows Kits.1\include\um\winnt.h(4991): error C2598: linkage specification must be at global scope
C:\Program Files (x86)\Windows Kits.1\include\um\winnt.h(5050): error C2156: pragma must be outside function
C:\Program Files (x86)\Windows Kits.1\include\um\winnt.h(5051): error C2156: pragma must be outside function
C:\Program Files (x86)\Windows Kits.1\include\um\winnt.h(5052): error C2156: pragma must be outside function
C:\Program Files (x86)\Windows Kits.1\include\um\winnt.h(5053): error C2156: pragma must be outside function
C:\Program Files (x86)\Windows Kits.1\include\um\winnt.h(5054): error C2156: pragma must be outside function
C:\Program Files (x86)\Windows Kits.1\include\um\winnt.h(5055): error C2156: pragma must be outside function
C:\Program Files (x86)\Windows Kits.1\include\um\winnt.h(5078): error C2156: pragma must be outside function
C:\Program Files (x86)\Windows Kits.1\include\um\winnt.h(5079): error C2156: pragma must be outside function
C:\Program Files (x86)\Windows Kits.1\include\um\winnt.h(5134): error C2156: pragma must be outside function
C:\Program Files (x86)\Windows Kits.1\include\um\winnt.h(5135): error C2156: pragma must be outside function
C:\Program Files (x86)\Windows Kits.1\include\um\winnt.h(5136): error C2156: pragma must be outside function
C:\Program Files (x86)\Windows Kits.1\include\um\winnt.h(5137): error C2156: pragma must be outside function
C:\Program Files (x86)\Windows Kits.1\include\um\winnt.h(15420): error C2059: syntax error: 'constant'
C:\Program Files (x86)\Windows Kits.1\include\um\winnt.h(15420): error C2238: unexpected token(s) preceding ';'
C:\Program Files (x86)\Windows Kits.1\include\um\winnt.h(15439): error C2059: syntax error: 'constant'
C:\Program Files (x86)\Windows Kits.1\include\um\winnt.h(15439): error C2238: unexpected token(s) preceding ';'

但是如果我注释行 #define N 666 文件将编译正常。谁能向我解释这里发生了什么?因为我不明白,docs 没有解决任何问题。

您不应该使用 "N" 这样的短名称来定义宏。这几乎有 100% 的可能性会与你之后包含的 header 中的某些东西发生冲突,比如 Windows.h:如果在其中的某个地方提到了 "N",预处理器会将其替换为 666 ,可能会使程序 ill-formed 或导致其他难以调试的怪异 pre-processor 效果,并且对 header 文件的任何用户(包括您自己)来说都是一场噩梦。

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

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

这将解析为

#include <windows.h>
#define N666

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

类对象宏 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 的默认链接是外部的)