小编Mac*_*dek的帖子

是否可以在 GCC/GNU C 中编写一个 _Static_assert 来验证编译时内存中位字段的布局?

假设我有以下定义:

#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)

c gcc static-assert assertion bit-fields

8
推荐指数
1
解决办法
291
查看次数

在## 运算符存在的情况下,可变参数 GNU C 预处理器宏的惊人扩展

如果我们定义一个宏

#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相同)

c gcc c-preprocessor variadic-macros

4
推荐指数
1
解决办法
135
查看次数