【问题标题】:C vs C++ why is this macro not expanded to a constant?C vs C++ 为什么这个宏不扩展为常量?
【发布时间】:2021-12-28 22:34:31
【问题描述】:

我正在使用 gcc/g++。下面的代码使用gcc -S test.c 编译得很好,但是使用g++ -S test.cpp 我得到error: requested alignment is not an integer constant。如果我查看两者的预处理器输出,它看起来是相同的。所以我的问题是为什么 ALIGN_BYTES 在 C++ 案例中不被预处理器评估为常量 64? (如果我用常量 64 替换 ALIGN_BYTES 就可以了)

/* test.c, test.cpp */
#define BITS 512
#define ALIGN_BYTES (BITS / 8)

#define ALIGN __attribute__ ((aligned(ALIGN_BYTES)))

typedef char* ALIGN char_PT;

【问题讨论】:

  • __attribute__ 是一个 gcc 扩展,所以看看那里。 C11有_Alignas,C++11有alignas
  • 删除了之前的评论,#define ALIGN alignas(ALIGN_BYTES) 确实解决了这个问题。谢谢

标签: c++ c gcc g++ c-preprocessor


【解决方案1】:

这不是宏扩展问题。此处的宏未在 C 或 C++ 中扩展为常量。预处理器不做算术运算,所以它只是生成表达式512 / 8,它不是一个常量,但编译器绝对应该能够将其减少为一个。

预处理器在这里为 C 和 C++ 生成相同的代码,但是 GCC(出于我不明白的原因)在两种语言中对 __attribute__ 扩展名的处理方式不同。我真的不知道为什么,可能有很好的理由,但其他人将不得不解释这一点。

如果你编译 C,gccaligned((512 / 8)) 很满意,但如果你用 g++ 编译 C++,它会抱怨 512 / 8 不是常量。我猜是对的,但实际上也是错的。

还有其他情况正好相反,g++ 对非常数感到满意,但 gcc 不满意。例如,如果您声明 static const int,您可以在 C++ 中的 __attribute__((aligned(...)) 中使用它,但不能在 C 中使用它。同样,我无法解释原因。这是一个编译器扩展,GCC 可以做任何事情。并且由于某种原因,它会在这里区别对待两种语言。

/* g++ will complain about this one; gcc will not */
typedef char *__attribute__((aligned((512 / 8)))) char_PT;

/* gcc will complain about this one; g++ will not */
static const int A = 16;
typedef char *__attribute__((aligned(A))) char_PT2;

不过,我想,既然我们知道一个版本适用于 C,而另一个版本适用于 C++,我们可以这样做:

#define BITS 512

#ifdef __cplusplus
static const unsigned int ALIGN_BYTES = BITS / 8;
#define ALIGN __attribute__((aligned(ALIGN_BYTES)))
#else /* C */
#define ALIGN_BYTES (BITS / 8)
#define ALIGN __attribute__((aligned(ALIGN_BYTES)))
#endif

typedef char *ALIGN char_PT;

【讨论】:

    【解决方案2】:

    正如@Deduplicator 所建议的,__attribute__ 是一个 gcc 扩展。使用以下解决了问题。

    #ifdef __cplusplus
    #define ALIGN alignas(ALIGN_BYTES)
    #else
    #define ALIGN __attribute__ ((aligned(ALIGN_BYTES)))
    #endif
    

    【讨论】:

    • 供c使用_Alignas
    • @tstanisl _Alignas 说它不能用于typedef
    猜你喜欢
    • 2011-03-01
    • 1970-01-01
    • 2012-02-08
    • 1970-01-01
    • 2018-09-29
    • 1970-01-01
    • 2015-04-25
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多