为什么在SUCCEEDED宏中有这么多括号?

时间:2010-06-25 12:36:51

标签: c com macros c-preprocessor

Windows SDK具有SUCCEEDED宏:

#define SUCCEEDED(hr) (((HRESULT)(hr)) >= 0)
-----------------------^-------------^-----

与其他宏一样,有明确的括号来确保编译器对意图的正确解释。

我没有得到的是(HRESULT)(hr)周围有括号的原因(我用^字符标记了它们)。括号hr以便可以存在一些复杂的构造,HRESULT括起来形成C样式的强制转换,然后整个>=构造也被括号括起来,为什么额外的对括号(HRESULT)(hr)附近?

8 个答案:

答案 0 :(得分:8)

C标准使得演员的优先级高于比较,因此编译器不需要parens。

然而,人们阅读宏定义,并将它们放入使得优先级明确,因此对于阅读它的人来说,显然它是将((HRESULT)hr)与零进行比较而不是强制转换结果的结果。比较而不必考虑优先权。

答案 1 :(得分:5)

额外的括号不会改变含义,但它们确实使优先级显式化。如果没有它们,那些不了解所有优先规则的读者就必须弄清楚表达的含义。

为了澄清,我只是指问题中标记的演员表达式周围的括号。其他是必要的(除非宏仅用于C ++而不是C,在这种情况下,您可以将(HRESULT)(hr)更改为HRESULT(hr))。

答案 2 :(得分:3)

简短回答:谁知道MS开发人员的想法。但是,hr附近的括号显然是必要的,因为hr可以是由多个操作数组成的表达式。据我所知,围绕((HRESULT)(hr))的括号是不必要的。这可能只是出于一种谨慎的习惯:在使用预处理器时,最好有太多括号而不是太少。

答案 3 :(得分:3)

这是为了应对宏观缺陷 - 它们只是一个文本替代品!

想象下面的宏

#define DOUBLE(x) x*2

int v = DOUBLE(1+1); // == 1+1*2 == 3. Did you expect 4?

因此宏的经验法则是:

  • 只有在没有其他方法可以解决您的问题时才使用它们
  • 将所有参数包装在parantheses中(以避免上述问题)
  • 将整个表达式包装在parantheses中(以避免其他类似的问题)
  • 使每个参数只出现一次(以避免副作用问题)

所以,一个更好的宏将是:

#define DOUBLE(x)((x)* 2)

你几乎就在那里,你们这个例子中剩下的parantheses是由于演员。


所以我们可以批评两点:

问:为什么它是宏,而不是内联函数?
A:向后兼容性。 C没有内联函数(或者至少没有),使用大约数千个此类声明的函数会导致当时大多数编译器失效。

问:此特定宏确实需要parantheses吗? A:我不知道。正式证明(或反证)可能需要半个小时或更长时间才有正确的参数和“呼叫”环境,这会产生意想不到的影响。我宁愿遵循上面提到的明智的指导方针,继续编码。

答案 4 :(得分:3)

作者只是愚蠢。所有额外的括号(在演员周围)都会使视觉解析变得更难。任何认为比较可能具有比铸造更高优先级的人需要在编码之前学习语言的基础知识......更不用说只是获得一些常识。

答案 5 :(得分:2)

括号确保元素按正确的顺序排列。您不希望编译器执行:

  1. (hr) >= 0

  2. 将结果转换为HRESULT

  3. 相反,您只想将(hr)表达式转换为HRESULT,然后将其与0进行比较。

答案 6 :(得分:1)

确保在比较之前将hr转换为HRESULT,而不是HRESULT(hr> = 0)。

答案 7 :(得分:0)

确保从(hr)扩展的表达式转换为HRESULT,然后将其与0进行比较。