2017-10-15 3 views
0

gibt diesen Satz von 4 Dateien:Fehler C2156: Pragma muss außerhalb der Funktion sein - warum passiert es in diesem Fall?

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" 

Wenn ich versuche, file2.cpp mit Visual Studio 2015 Compiler cl -c file2.cpp zu kompilieren ich ein paar Fehler zu bekommen:

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 ';' 

Aber wenn ich die Linie #define N 666 die Datei Kommentar wird ok kompiliert werden. Kann mir jemand erklären, was hier vor sich geht? Weil ich es nicht verstehe, docs lösen mich nichts.

+3

Verstehen [was das Makro tut dies tatsächlich] (http://en.cppreference.com/w/cpp/preprocessor/replace) und bedenken Sie, dass 'N' ein häufig verwendeter Bezeichner ist. – chris

+0

Meine beste Vermutung wäre, dass Ihre Makrodefinition etwas im Header 'um/winnt.h' klemmt, das anscheinend von' windows.h' enthalten ist. In diesem Fall sollte das Umkehren der Reihenfolge der # include-Anweisungen in file2.cpp das Problem ebenfalls beheben. –

+0

Warum ein Makro verwenden, wenn ein 'const int' ausreichen würde? Und warum ist es global? Und warum hat es keinen besseren, beschreibenden Namen als "N"? –

Antwort

2

Das Objekt-ähnliche Makro N kollidiert mit windows.h, die winnt.h enthält.

Zum Beispiel:

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

würde ich vorschlagen, mit Hilfe von Makros zu vermeiden, wann immer Sie können. In C und C++, könnten Sie die Makrodefinition mit konstantem Objekt ersetzen:

const int N = 666; 

(die in C beachten Sie wahrscheinlich static const verwenden, da die Standard-Verknüpfung von const extern ist)

+0

Danke, ich wusste nicht, dass Makro in der 'windows.h' Datei sichtbar wäre – BPL

1

Sie sollten keine Makros mit so kurzen Namen wie "N" definieren. Mit fast 100% Wahrscheinlichkeit wird dies mit etwas kollidieren innerhalb der Header, die Sie später einschließen, wie Windows.h: Wenn irgendwo in ihm ein "N" erwähnt wird, wird der Präprozessor es durch 666 ersetzen, möglicherweise macht das Programm schlecht gebildet oder verursacht andere seltsame Pre-Prozessor-Effekte, die schwer zu debuggen sind und ein Alptraum für jeden Benutzer Ihrer Header-Datei, einschließlich Sie selbst.

Wie auch immer, wenn Sie darauf bestehen, es zu tun (was Sie sollten wirklich nicht, vor allem in Header-Dateien), stellen Sie sicher, dass Sie #define N nach jeder Header einschließlich:

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

, die

lösen wird

Nebenbei arbeitet der Präprozessor, die Reihenfolge, in der Sie pro Übersetzungseinheit einschließen, ist wichtig.

Verwandte Themen