2014-10-06 13 views
39

Ich erwarte den folgenden Code zu kompilieren. Clang und VC++ geben beide einen Fehler in der Zeile mit else.Wenn und ohne Klammern

void MyFunction(std::int32_t& error) 
{ 
    std::int32_t variable = 0; 
    if(GetSomething()) 
     error = EOK; 
    else 
     error = ERROR; 
} 

Wenn ich setzen geschweiften Klammern um error = EOK;, dann kompiliert. Warum VC++ sagen:

illegal sonst ohne passende wenn

?


Mein vollständiger Code ist unten, ersetzt std :: uint32_t mit einem typedef. Es gibt immer noch den gleichen Fehler in VC++.

using sint32 = int; 

#define ERROR 5; 
#define EOK 0; 

bool GetSomething(); 

void MyFunction(sint32& error) 
{ 
    sint32 variable = 0; 
    if (GetSomething()) 
     error = EOK; 
    else 
     error = ERROR; 
} 
+80

Ich rieche ein Makro Ratte. –

+2

was ist EOK (oder GetSomething)? vielleicht ist es eine etwas verwurstete Makrodefinition – marcinj

+0

@Graznarak post die vollständige Quelle, einschließlich aller Makros, die Sie definiert haben, weil diese Quelle für mich kompiliert –

Antwort

94

Wenn Ihre Definition von EOK ist wie folgt:

#define EOK 0;

dann wäre es diese Art von Fehler verursachen, weil sie gewaltsam die if-Anweisung beendet, bevor das sonst erreicht ist, es macht ein anderes ohne ein passendes wenn. Der Compiler sieht diesen Code nach Makro Ersatz:

if(GetSomething()) 
    error = 0;; 
else 
+17

besser noch eine Konstante verwenden, kein Makro! – Mgetz

+60

Ugh, Semikolon-terminierte Makros. Das Pure Böse. – ApproachingDarknessFish

+27

Grund # 245, warum Steueranweisungen ohne geschweifte Klammern * nur * nach Problemen fragen ... – sapi

15

Hier ist eine mögliche Lösung:

enum 
{ 
    EOK = 0, 
    ERROR = 5 
}; 

Beachten Sie, dass alle Bezeichner mit E entweder durch einen anderen Großbuchstaben oder eine Zahl für die Verwendung reserviert beginnt, gefolgt als Makro-Namen von <cerrno>, so um Namenskonflikte zu vermeiden, eine andere Namenskonvention für Ihre Fehler zu verwenden.

+2

Besser, dass eine Klasse Enum für schönere Namen Abstand, auch dann würde es nicht mit E die ganze Zeit beginnen müssen: D –

0

implest und effizienter werden, können Sie tun:

error = (GetSomething()) ? 0 : 5 ; 

Und wenn Sie mit ENUM zu wollen wie Matt sagen, werden sie:

error = (GetSomething()) ? enum.EOK : enum.ERROR ; 
+0

* error = (GetSomething())? enum.EOK: enum.ERROR; – karim

+0

Ich bestreite Ihren Anspruch, dass dies effizienter ist. Der Compiler sollte den gleichen Code generieren. –

+0

Sebastian, eine Codezeile ist einfacher für den Compiler und auch für den Entwickler (und auch als Komplexitätsseite;)) – karim

Verwandte Themen