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

旧版G++(3.3.5及更早)下常量表达式编译时检查宏的修复

兼容旧版G++(3.3.5及更早)的编译时检查宏修改方案

我是一名C程序员,对C了解有限。我编写了用于编译时检查的Chk和CEx宏,用于在常量表达式中嵌入编译时检查:Chk验证表达式为真(编译时常量),求值为0;CEx确保表达式是编译时常量,求值为表达式本身,不满足则终止编译。这些宏在G 4.1.1上正常工作,但在G++ 3.3.5及更早版本中编译C++代码时会出现解析错误:

$ gcc -x c++ -c x
x:22: error: parse error before `)' token
x:23: error: parse error before `)' token

原代码如下:

/* in-expression compile-time check evaluating to 0 */
#ifdef __cplusplus
template<bool> struct Chk_sa;
template<> struct Chk_sa<true>{};
#define Chk(test) (sizeof((Chk_sa<!!(0+(test))>())) * 0)
#else
#define Chk(test) (sizeof(struct { int (Chk):((0+(test)) ? 1 : -1); }) * 0)
#endif

/* ensure value x is a constant expression */
#ifdef __cplusplus
template<bool,bool> struct CEx_sa;
template<> struct CEx_sa<true,false>{};
template<> struct CEx_sa<false,true>{};
#define CEx(x) (sizeof((CEx_sa<!!(0+(x)), !(0+(x))>())) * 0 + (x))
#else
#define CEx(x) (sizeof(struct { int (CEx):(((0+(x)) && 1) + 1); }) * 0 + (x))
#endif

/* usage like this: */
struct ChkTest {
        int expr1[Chk(3*3) + 1];  // supposed to be [1]
        int expr2 : CEx(3*3);     // supposed to be : 9
};

问题原因

旧版G++(3.3.x系列)对C++模板语法的解析更为严格,无法正确处理sizeof((Chk_sa<...>()))这种写法——它会把模板实例化后的括号()误解析为语法错误,而不是空结构体的临时对象构造。

修改后的代码

/* in-expression compile-time check evaluating to 0 */
#ifdef __cplusplus
template<bool> struct Chk_sa;
template<> struct Chk_sa<true>{};
// 移除多余的括号和临时对象构造,直接取类型的sizeof
#define Chk(test) (sizeof(Chk_sa<!!(0+(test))>) * 0)
#else
#define Chk(test) (sizeof(struct { int (Chk):((0+(test)) ? 1 : -1); }) * 0)
#endif

/* ensure value x is a constant expression */
#ifdef __cplusplus
template<bool,bool> struct CEx_sa;
template<> struct CEx_sa<true,false>{};
template<> struct CEx_sa<false,true>{};
// 同样移除多余的括号和临时对象构造
#define CEx(x) (sizeof(CEx_sa<!!(0+(x)), !(0+(x))>) * 0 + (x))
#else
#define CEx(x) (sizeof(struct { int (CEx):(((0+(x)) && 1) + 1); }) * 0 + (x))
#endif

/* usage remains unchanged */
struct ChkTest {
        int expr1[Chk(3*3) + 1];  // 仍为[1]
        int expr2 : CEx(3*3);     // 仍为:9
};

修改原理

  • 空结构体Chk_sa<true>和CEx_sa的sizeof值为1,乘以0后仍为0,完全保留原Chk宏的求值结果
  • CEx宏中sizeof(...) *0仍为0,加上x后结果不变,保留原功能
  • 移除临时对象构造()后,旧G++能正确解析模板类型的sizeof表达式,避免语法错误

功能验证

修改后的宏在G++ 3.3.5中可以正常编译,同时保留原有的编译时检查功能:

  • 若Chk的参数为假(或非编译时常量),编译器会因找不到Chk_sa<false>的定义而报错
  • 若CEx的参数非编译时常量,编译器无法推导模板参数,会报实例化错误;若参数为常量,仅匹配对应的特化版本,正常通过编译

内容的提问来源于stack exchange,提问作者mirabilos

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.04 23:27:23