【问题标题】:What does #define (integer) do?#define (integer) 有什么作用?
【发布时间】:2021-09-01 03:21:49
【问题描述】:

当然是一个重复,我会尽快将其删除,我会遇到答案。我只是找不到我要找的东西。

c 中的这两行是什么意思?

#define NN_DIGITS     (  4)
#define MM_MARKS_DONE (255)

我知道#define#define () 做了什么,其中#define () 执行() 中的宏,但我不知道这个特别的警告(带有整数)。

写下()来定义一个整数值实际上是多余的吗?这个值应该按位解释吗?如果我们不写() 会发生什么。 4和255会被当成字符串吗?

【问题讨论】:

    标签: c


    【解决方案1】:

    在这种情况下,括号完全没有任何作用 - 它只是噪音。

    生存的一般规则是,类函数宏应该始终:

    1. 将每次出现的宏参数括在括号中,然后
    2. 将整个宏包在外括号中

    即:

    #define ADD(x,y) x + y       // BAD
    #define ADD(x,y) (x) + (y)   // BAD
    #define ADD(x,y) ((x) + (y)) // correct
    

    这是为了避免运算符优先级的问题,任何体面的初学者级学习材料都会解决这个问题。

    学习了上述规则的过于迂腐的人倾向于将它们应用于所有宏,而不仅仅是类似函数的宏。但是,如果宏只包含一个整数常量(一个预处理器标记),那么括号绝对没有任何作用。

    写下()定义一个整数值其实是多余的吗?

    是的,它只是增加了噪音。

    这个值应该按位解释吗?

    宏大多只是作为文本替换。你对调用代码中的值做什么与宏无关。

    如果我们不写 () 会发生什么

    代码将变得更容易阅读。

    4 和 255 会被当作字符串吗?

    不,他们为什么会这样。

    在特定情况下,括号会造成伤害,那就是当您使用宏将预处理器常量转换为字符串时。假设我有这个程序:

    #define STR(x) #x
    #define AGE(x) STR(x)
    #define DOG_AGE 5
    
    int main(void)
    {
      puts("My dog is " AGE(DOG_AGE) " years old.");
    }
    

    AGE 将宏 DOG_AGE 扩展为 5,然后下一个宏将其转换为字符串。所以这会打印出My dog is 5 years old.,因为# 运算符会完全按照给定的方式转换预处理器令牌。如果我在宏中添加“无用的噪音括号”:

     #define DOG_AGE (5)
    

    然后输出变成My dog is (5) years old. 不是我想要的。

    【讨论】:

      【解决方案2】:

      关键字:“执行”。这是你误会的根源。

      不执行宏。他们被替换了。预处理器将标记NN_DIGITS 替换为标记序列( 4)。事实上,它将用几乎 any 标记序列替换它。甚至#define NN_DIGITS ( %34 (DDd ] 也是一个有效的宏定义(由我的猫提供),尽管我们当然不想尝试扩展它。

      写下()定义一个整数值其实是多余的吗?

      从实际的角度来看,是的,它是多余的。但有些人可能会这样做以保持与其他宏的一致性,其中结果表达式可能取决于括号的存在。

      这个值应该按位解释吗?

      对于计算机来说,一切都是按位计算的。

      如果我们不写 () 会发生什么。 4和255会被当作字符串吗?

      不,它只是标记4255,而不是序列( 4)(255)。预处理器只处理令牌,它对类型系统几乎一无所知。如果宏出现在程序中,说:

      int a = NN_DIGITS;
      

      它会被预处理器变成:

      int a = (  4);
      

      然后通过将程序转换为可执行文件的管道中的其他步骤进一步编译。

      【讨论】:

      • 太棒了。 “宏不被执行而是被替换”。非常感谢您的宝贵时间!
      • 在某些情况下,定义 (4) 而不是 4 会有所作为:Is there a good reason for always enclosing a define in parentheses in C?
      • @phuclv - 这与我希望这个答案的水平高度无关。在解释宏被替换的简单事实时提及串联巫术将主要用于混淆。
      • @phuclv 事实上,() 的使用实际上是一个很好的做法,很高兴知道。非常感谢您的宝贵时间!
      • 请用您的猫的更多信息更新此答案。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多