2014-10-06 90 views
39

我期望下面的代码进行编译。 Clang和VC++都给我一个错误else如果和没有大括号

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

如果我把大括号括在error = EOK;左右,那就编译。为什么VC++说:

非法否则如果没有

匹配?


我的完整代码如下,用typedef替换std :: uint32_t。它仍然在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

我闻宏老鼠。 – 2014-10-06 20:01:35

+2

什么是EOK(或GetSomething)?也许它的一些宏观定义 – marcinj 2014-10-06 20:01:59

+0

@Graznarak发布完整的源代码,包括你定义的任何宏,因为这个源码本身就为我编译 – 2014-10-06 20:02:53

回答

94

如果您EOK的定义如下:

#define EOK 0;

那么它会导致这种类型的错误,因为它强行终止if语句到了else之前,使它否则没有匹配的if。编译器看到宏替换此代码后:

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

更好的是使用一个常量而不是宏! – Mgetz 2014-10-06 20:06:32

+60

呃,以分号结束的宏。纯粹的邪恶。 – ApproachingDarknessFish 2014-10-06 20:07:36

+27

原因#245为什么没有大括号的控制语句只是*要求*的问题... – sapi 2014-10-07 00:08:45

15

这里是一个可能的解决办法:

enum 
{ 
    EOK = 0, 
    ERROR = 5 
}; 

注意,开始与E后接另一个大写字母或数字的所有标识符被保留用作宏名称<cerrno>,因此为了避免名称冲突,请考虑对您的错误使用不同的命名约定。

+2

更好的做一个类名为更好的名称间距的枚举,也不必始终以E开头:D – 2014-10-07 06:25:52

0

待implest和更有效,你可以这样做:

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

如果你想与枚举马特说,它变成了:

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

* error =(GetSomething())? enum.EOK:enum.ERROR; – karim 2014-10-10 10:00:10

+0

我反驳你的说法,认为这样更有效率。编译器应该生成相同的代码。 – 2014-10-10 13:03:51

+0

塞巴斯蒂安,一行代码对编译器和开发人员来说都更简单(也作为一个复杂的一面;)) – karim 2014-10-10 14:07:57