假设我有以下定义:
#include <stdbool.h>
#include <stdint.h>
#define ASSERT(cond) _Static_assert(cond, #cond)
typedef union {
struct {
bool bit0:1;
bool bit1:1;
bool bit2:1;
bool bit3:1;
bool bit4:1;
bool bit5:1;
bool bit6:1;
bool bit7:1;
};
uint8_t bits;
} byte;
ASSERT(sizeof(byte) == sizeof(uint8_t));
Run Code Online (Sandbox Code Playgroud)
能不能写个代码,比如
#include <assert.h>
// ...
assert(((byte) { .bit0 = 1 }).bits == 0b00000001);
assert(((byte) { .bit1 = 1 }).bits == 0b00000010);
assert(((byte) { .bit2 = 1 }).bits == 0b00000100);
assert(((byte) { .bit3 = 1 }).bits == 0b00001000);
assert(((byte) { .bit4 = 1 …
Run Code Online (Sandbox Code Playgroud) 如果我们定义一个宏
#define M(x, ...) { x, __VA_ARGS__ }
Run Code Online (Sandbox Code Playgroud)
然后使用它传递自身作为参数
M(M(1, 2), M(3, 4), M(5, 6))
Run Code Online (Sandbox Code Playgroud)
然后它扩展到预期的形式:
{ { 1, 2 }, { 3, 4 }, { 5, 6 } }
Run Code Online (Sandbox Code Playgroud)
但是,当我们使用##
运算符时(为了防止在单参数调用的情况下在输出中出现悬空逗号,如GCC 手册中所述),即
#define M0(x, ...) { x, ## __VA_ARGS__ }
Run Code Online (Sandbox Code Playgroud)
那么在参数的扩展
M0(M0(1,2), M0(3,4), M0(5,6))
Run Code Online (Sandbox Code Playgroud)
似乎在第一个参数后停止,即我们得到:
{ { 1,2 }, M0(3,4), M0(5,6) }
Run Code Online (Sandbox Code Playgroud)
这种行为是一个错误,还是源于某些原则?
(我也用clang检查过它,它的行为方式与GCC相同)