【问题标题】:Are C macros implicitly cast?C 宏是隐式转换的吗?
【发布时间】:2014-07-31 13:54:33
【问题描述】:

我已经搜索过 SO,但没有找到这个特定问题的答案。如果已经回答,请见谅。

如果您有以下情况:

#define MACRO  40

您不会将它分配给您在循环中使用它的变量:

for(int i = 0; i < MACRO; i++) {...

然后,perprocessor 创建:

for(int i = 0; i < 40; i++) {...

由于比较类型为int i,编译器是否会将其隐式转换为int?我看过这个问题Type of #define variables,Edgar Bonet 的很多答案暗示编译器选择如何处理宏有一个顺序?

这个问题,How does C++ implicitly cast arguments to a comparator such as <?,也有人建议,但只描述了隐式转换如何与两种类型进行比较。由于宏实际上没有类型,我不确定这是否适用。

【问题讨论】:

  • 40 已经是int
  • A C 宏只是一个文本替换。
  • C 宏只是文本替换。它的行为就像你在那里输入了40
  • 编译器完全不知道40 来自宏。在预编译器完成替换后,编译器会正确分析代码。
  • 宏没有类型,但有替换文本,但40 有。扩展宏后,它的行为就像您输入了 text/。

标签: c++ c macros types c-preprocessor


【解决方案1】:

C 中,宏只是替换文本,这意味着复制宏所代表的文本而不是宏名称,您甚至可以在宏中放置 C 关键字。

#define [identifier name] [value]

在代码中,标识符名称被替换为。你的定义是:

#define MACRO  40

40 已经是一个 int。 所以for(int i = 0; i &lt; 40; i++) 不需要演员表。

【讨论】:

    【解决方案2】:

    preprocessor 在编译器看到任何东西之前就扩展了宏。通过转到draft C99 standard 部分6.4.8 预处理数字,我们可以看到预处理数字没有类型:

    预处理数字没有类型或值;它同时获得 在成功转换(作为翻译阶段 7 的一部分)后 浮动常量令牌或整数常量令牌。

    C++ 标准草案中的同一部分是2.10

    正如我们在C preprocessor Wikipedia article 中看到的,宏扩展发生在第 4 阶段。

    C 术语中的整数常量和 C++ 术语中的整数文字的转换在草案 C99 标准部分 6.4.4.1 整数常量 和第 5段中的下表中进行了介绍> 上面写着:

    整数常量的类型是对应列表的第一个 其价值体现在哪里

    八进制或十六进制 后缀 十进制常数 常数 -------------------------------------------------- ------------------------- 无 int int long int 无符号整数 long long int long int 无符号长整数 长长整数 unsigned long long int -------------------------------------------------- ------------------------- u 或 U unsigned int unsigned int 无符号长整数 无符号长整数 unsigned long long int unsigned long long int -------------------------------------------------- ------------------------- l 或 L long int long int long long int 无符号 long int 长长整数 unsigned long long int -------------------------------------------------- ------------------------- u 或 U unsigned long int unsigned long int 和 l 或 L unsigned long long int unsigned long long int -------------------------------------------------- ------------------------- ll 或 LL long long int long long int unsigend long long int -------------------------------------------------- ------------------------- u 或 U unsigned long long int unsigned long long int 和 ll 或 LL -------------------------------------------------- -------------------------

    表格是来自answer 的表格的修改版本。 C++ 标准草案中涵盖此内容的部分是 2.14.2 部分,其中也有一个类似的表格。

    因此,在您的示例中,40 没有后缀并且是十进制常量,并且可以从表的该部分表示的第一种类型是 int

    此时我们最终得到了将40&lt; 运算符一起使用的效果。由于i40 都是算术类型,因此将执行通常的算术转换,在这种情况下仍然是int。对于C99,这在6.3.1.8 部分和C++ 部分5 中有介绍。

    【讨论】:

    • 谢谢!这正是我正在寻找的答案类型。
    【解决方案3】:

    在 C 和 C++ 中,宏实际上是就地替换。预处理器将遇到这些#defines 并在找到它们时替换它们。这就是您可以在宏中嵌套宏的方式,并且只需 1 次即可进行预处理。

    【讨论】:

      【解决方案4】:

      编译器永远不会看到宏;在将源文本输入编译器之前,预处理器会扩展所有宏。

      编译器看到的都是

      for(int i = 0; i < 40; i++) {...}
      

      常量表达式40的类型根据2011 C standard的6.4.4.1节或online C++ standard的2.13节的规则确定。

      【讨论】:

        【解决方案5】:

        C 宏只是文本替换,它们没有类型。涉及类型的所有操作都在宏替换之后完成,其行为与您在原始代码中键入替换一样。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2015-07-06
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多