I am using gcc/g . The below code compiles fine with gcc -S test.c
, however with g -S test.cpp
I get error: requested alignment is not an integer constant
. If I look at the preprocessor output for both it looks identical. So my question is why isn't ALIGN_BYTES
being evaluated to the constant 64 by the preprocessor in the C case? (If I replace ALIGN_BYTES
with the constant 64 it works fine)
/* test.c, test.cpp */
#define BITS 512
#define ALIGN_BYTES (BITS / 8)
#define ALIGN __attribute__ ((aligned(ALIGN_BYTES)))
typedef char* ALIGN char_PT;
CodePudding user response:
As @Deduplicator suggested, __attribute__
is a gcc extension. Using the below fixed the problem.
#ifdef __cplusplus
#define ALIGN alignas(ALIGN_BYTES)
#else
#define ALIGN __attribute__ ((aligned(ALIGN_BYTES)))
#endif
CodePudding user response:
It is not a macro expansion issue. The macro is not expanded to a constant in either C or C , here. The preprocessor does not do arithmetic, so it simply generates the expression 512 / 8
which isn't a constant, but which the compiler should definitely be able to reduce to one.
The preprocessor generates the same code for C and C here, but GCC (for reasons I do not understand) treats the __attribute__
extension differently in the two languages. I really have no idea why, there likely are good reasons, but someone else will have to explain that.
If you compile C, gcc
is happy with aligned((512 / 8))
, but if you compile C with g
it will complain that 512 / 8
is not a constant. It is right, I guess, but really also wrong.
There are other cases where it is the opposite, where g
is happy with a non-constant, but gcc
is not. If you declare a static const int
for example, you can use it in __attribute__((aligned(...))
in C but not in C. Again, I cannot explain why. It's a compiler extension and GCC can do whatever. And for some reason, it will treat the two languages differently here.
/* 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;
I suppose, though, that since we know one version that works with C and another that works with C , we could do this:
#include <stdalign.h> /* for 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;