You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Barr C编码标准2018示例代码存疑:两处问题是否为错误?

问题1:预处理指令中使用sizeof()的误区

你完全没理解错——标准C中,预处理阶段不能直接使用sizeof()。

预处理是编译流程的早期环节,此时编译器还未解析timer_reg_t这类自定义类型的定义,而sizeof()是编译时运算符,只有当类型被编译器识别后才能计算其大小。直接在#if预处理指令里调用sizeof()违反C标准,必然会触发你遇到的「missing binary operator before token "("」错误。

书中出现这样的示例大概率是笔误,或是针对少数支持非标准扩展的编译器编写的(这类扩展不具备通用性)。正确的做法是用编译时断言替代预处理检查:

  • C11及以后版本可直接用_Static_assert:
_Static_assert(sizeof(timer_reg_t) == 8, "timer_reg_t struct size incorrect (expected 8 bytes)");
  • 若要兼容更早的C标准,可利用数组声明的编译报错特性:
typedef char timer_reg_size_check[sizeof(timer_reg_t) == 8 ? 1 : -1];

问题2:缺失右括号的问题

你的判断完全正确——这就是单纯的输入错误。原代码里的#if ((8 != sizeof(timer_reg_t))少了一个闭合的右括号,正确写法应为:

#if (8 != sizeof(timer_reg_t))
// 或者保持双层括号的配对
#if ((8 != sizeof(timer_reg_t)))

额外补充:结构体填充的隐患

结合书中的规则a,你给出的结构体示例还有一个容易忽略的问题:即便手动添加了_unused字段,编译器仍可能因对齐规则插入填充字节。要彻底避免填充,必须使用编译器特定的属性或指令:

  • GCC/Clang环境下用__attribute__((packed)):
typedef struct __attribute__((packed))
{
    uint16_t count; // offset 0
    uint16_t max_count; // offset 2
    uint16_t _unused; // offset 4
    uint16_t enable : 2; // offset 6 bits 15-14
    uint16_t b_interrupt : 1; // offset 6 bit 13
    uint16_t _unused1 : 7; // offset 6 bits 12-6
    uint16_t b_complete : 1; // offset 6 bit 5
    uint16_t _unused2 : 4; // offset 6 bits 4-1
    uint16_t b_periodic : 1; // offset 6 bit 0
} timer_reg_t;
  • MSVC环境下用#pragma pack:
#pragma pack(push, 1)
typedef struct
{
    // 结构体成员...
} timer_reg_t;
#pragma pack(pop)

只有这样才能确保结构体大小严格为8字节,匹配外设寄存器的布局要求。

内容的提问来源于stack exchange,提问作者Daniel H Sagarra

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.30 14:27:23