【问题标题】:"#define BUF 8" vs "#define BUF (8)“#define BUF 8”与“#define BUF (8)
【发布时间】:2019-09-06 22:51:26
【问题描述】:

两者有什么区别(如果有的话):

#define BUF (8)

#define BUF 8

我在 c 编程方面不是很有经验,也从未见过只有 1 个数字的 #define 而不是将它放在括号中。

PS:代码是在 64 位 linux 系统上使用带有 -m32 标志的 gcc 编译的。所以最终的二进制文件是 32 位 ELF 可执行文件。

【问题讨论】:

  • 不,没有。当您想指定操作顺序或使您的代码更清晰时,您可以使用()
  • @Simon 略有不同。例如。 float x = sin BUF; 将在一种情况下编译,但在另一种情况下不会编译。
  • 是的..我相信那里的答案非常有用。我为自己没有找到这个而感到羞耻。
  • @Simon:是的,有区别。如果其他一些宏使用##BUF8 可能会产生一个有效的令牌,而(8) 不会。

标签: c


【解决方案1】:

如果是这样简单的宏定义 - 只是一个常量 - 没有必要将 8 包含在 () 中。这对() 可能会防止一些滥用,但这些例子是做作的和不切实际的。

但是一旦操作员参与进来,即被替换的文本打算成为一个表达式,添加那些()就变得更加重要了。例如,如果您有一系列相关的清单常量定义也涉及 值,则将这些 () 添加到使用一元 - 的替换是一个非常好的主意

#define CONSTANT_A 2
#define CONSTANT_B 1
#define CONSTANT_C 0
#define CONSTANT_D (-1)

在这种情况下,为了保持一致性,将它们全部包含在() 中可能是有意义的。这是个人品味的问题。

【讨论】:

    【解决方案2】:

    我无法想象在这种特殊情况下合理使用它会有什么不同,但请考虑一下:

    #define add(x,y) x+y
    
    int i=add(3,5)*2
    

    现在您会期望 i 的值为 16,对吗?但它会扩展为 i=3+5*2,从而使 i 的值为 13。

    HolyBlackCat 在评论中写道,float x = sin BUF; 在后一种情况下不会编译,这是完全正确的。但是,使用这样的宏是一个非常糟糕的主意。

    用括号括起来永远不会有坏处,而且通常会有所帮助。宏基本上只是一种高级复制粘贴。因此,如果您可以想象一段代码,其中字符序列(8) 会产生与8 不同的结果,那么这两个宏将以相同的方式不同。

    出于类似的原因,如果一个宏包含多个语句,最好将它们包含在一个 do-while 循环中。考虑一下:

    #define callMy2Funcs(x,y) \
        myFunc1(x); \
        myFunc2(y);
    

    现在这个:

    if(x>5) 
        callMy2Funcs(x,x);
    

    将扩展到

    if(x<5)
        myFunc1(x);
    myFunc2(x);
    

    而不是

    if(x<5) {
        myFunc1(x);
        myFunc2(x);
    }
    

    解决办法是这样的:

    #define callMy2Funcs(x,y) \
        do {\
            myFunc1(x); \
            myFunc2(y); \
        } while(0)
    

    【讨论】:

    • 据我所知#define 应该是一个常数
    • @Simon #define 定义了一个宏。有人说宏应该只用于定义常量。 (恕我直言,那些人错了!)
    • @ikegami 请不要在帖子新鲜时进行编辑。当我正在改进我的帖子时,这让我很烦。
    • @SergeyA 是的。固定。
    • @ikegami 对不起,我不是忘恩负义。但最好在评论中指出它。在旧帖子上,您可以在不发表评论的情况下对其进行编辑。感谢您修复它。
    【解决方案3】:

    范围内宏标识符的外观只需替换为替换文本即可。因此,这段代码...

    #define BUF 8
    #define BUF2 (8)
    
    x =  BUF * BUF2;
    

    ... 展开为

    x = 8 * (8);
    

    特别是,括号是替换文本的一部分,而不是宏定义的一部分。 (但不要将此与类似函数的宏定义混淆,其中标识符和左括号之间没有空格。)

    在这种情况下,这两个宏定义几乎可以使用,但不能完全互换使用。然而,括号在其他情况下会产生更大的差异。考虑一下:

    #define MY_SIZE 16 + 7
    #define MY_SIZE2 (16 + 7)
    
    void *x = malloc(8 * MYSIZE);
    void *y = malloc(8 * MYSIZE2);
    

    它扩展到

    void *x = malloc(8 * 16 + 7);
    void *y = malloc(8 * (16 + 7));
    

    ,为xy预留不同数量的内存。

    【讨论】:

      猜你喜欢
      • 2020-06-28
      • 2010-12-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-01-27
      相关资源
      最近更新 更多