标准C预处理宏计算带副作用双操作数最大值的实现方案咨询
存在的XY问题说明
你当前的核心需求是为两个互斥使用的哈希工作上下文分配一块大小足够、对齐合法的共享内存,当前通过对两个上下文尺寸做按位或计算数组长度的实现属于绕路方案,存在两个缺陷:
- 按位或得到的尺寸必然大于等于两个尺寸的真实最大值,会产生不必要的内存浪费,例如
CTX_BYTES(hmsg)=256、CTX_BYTES(hmgf)=128时,按位或结果为384,比实际需要的256多占用128字节内存 - 直接定义
uint8_t数组没有处理两个哈希上下文的对齐要求,如果两者对齐要求不同,可能触发未对齐访问的未定义行为
最优解决方案(适配共用上下文场景)
直接通过共用体(union)定义共享上下文区域,由编译器自动计算所需的尺寸和对齐,完全不需要手动计算最大值,纯标准C实现,且只要CTX_BYTES入参为常量表达式,结构大小就是常量表达式:
// 调整类型定义宏,直接内嵌union声明共享上下文 #define PKCS1_PADDING_ORACLES_T(hmsg, hmgf) \ struct { \ pkcs1_padding_oracles_base_t base; \ union { \ uint8_t msg_ctx[CTX_BYTES(hmsg)]; \ uint8_t mgf_ctx[CTX_BYTES(hmgf)]; \ } hashctx; \ } // 要获取结构尺寸直接用sizeof即可,不需要单独的SIZE计算宏 typedef PKCS1_PADDING_ORACLES_T(macro_SHA256, macro_SHA1) pkcs1_sha256_sha1_oracles_t; #define PKCS1_SHA256_SHA1_ORACLES_SIZE sizeof(pkcs1_sha256_sha1_oracles_t)
该方案完全满足你的所有约束:两个入参仅在CTX_BYTES调用时求值一次,不需要手动定义额外变量,结果完全符合C标准要求,对齐安全也由编译器保证。
通用双操作数最大值宏实现方案
如果你确实需要独立的最大值计算宏,纯标准C下无法同时实现「支持带副作用的入参单次求值」和「结果始终为常量表达式」,可按场景选择实现:
- 入参均为常量表达式场景:直接用三元运算符即可,结果为标准常量表达式:
#define MAX_CONST(a, b) ((a) > (b) ? (a) : (b))
- 入参可能带副作用场景:如果允许使用编译器通用扩展(大部分主流编译器包括GCC、Clang、MSVC都支持),可用语句表达式实现入参单次求值:
#define MAX(a, b) ({ \ typeof(a) _a = (a); \ typeof(b) _b = (b); \ _a > _b ? _a : _b; \ })
如果你需要严格符合标准C,要求入参可能带副作用时由调用方先将入参求值存入临时变量,再传入MAX_CONST宏即可避免重复求值。
当前按位或方案的可行性说明
你当前使用的按位或方案确实可以满足「共享空间足够容纳任意一个上下文」的要求,在不介意少量内存浪费、且两个上下文对齐要求一致的场景下可以正常使用。
内容的提问来源于stack exchange,提问作者DannyNiu
相关产品推荐
相关产品推荐

