【问题标题】:Using multiplied macro in array declaration在数组声明中使用乘宏
【发布时间】:2013-07-30 10:26:41
【问题描述】:

我知道以下是有效代码:

#define SOMEMACRO 10
int arr[SOMEMACRO];

结果为@​​987654322@。

如果我想创建一个 2 倍大小的数组(并且仍然需要其他地方的原始宏),这是有效的代码吗?

#define SOMEMACRO 10
int arr[2 * SOMEMACRO];

预编译后为int arr[2 * 10]。这仍然被编译器视为常量表达式吗?

快速浏览后它似乎可以工作,但这是定义的行为吗?

【问题讨论】:

  • 是的,这是在编译时评估并用作常量。

标签: c arrays macros


【解决方案1】:

是的,它会起作用。宏将在编译时放置,因此a[2*SOMEMACRO] 将变为a[2*10],这是完全有效的。

要检查预处理的内容,您可以使用cc -E foo.c 选项

【讨论】:

    【解决方案2】:

    这仍然被编译器视为常量表达式吗?

    是的。这就是常量表达式和文字之间的区别:常量表达式不必是 single 文字,它可以是任何可以在编译时计算其值的表达式(即文字的组合或其他常量表达式)。

    (为了清楚起见:当然文字仍然被认为是常量表达式。)

    但是,在 C 中,数组的大小不必是编译时常量。 C99 和 C11 支持变长数组 (VLA),所以

    size_t sz = // some size calculated at runtime;
    int arr[sz];
    

    也是有效的 C。

    【讨论】:

      【解决方案3】:

      是的,您可以使用此表达式。它不会导致 UB。
      请注意,数组下标可能是一个整数表达式

      #define i  5 
      #define j  4
      int a[i+j*10] = 0;
      

      下标i+j*10的值将在编译时计算。

      【讨论】:

        【解决方案4】:

        是的,只要它是一个有效的数字,它就是一个常量表达式。 如果你说它有效,那么你就知道编译器可以很好地处理它。

        你知道我们做不到

        int x;
        scanf("%d", &x);
        int arr[2 * x];
        

        因为这不是一个常数。但是你写的是一个常数,所以你很高兴

        【讨论】:

        • 我认为第二个我们可以使用新的编译器
        • “我们做不到”——我们可以,你碰巧活在 1999 年之前吗?
        • 这在 C99 中有效。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-10-24
        • 2011-07-18
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多