如何编写C宏定义以在编译时迭代并修改字符串字符
如何定义_MODIFY预处理器宏实现编译时字符异或修改
要实现编译时将字符串每个字符与指定常量异或的需求,核心难点在于标准C预处理器无法直接遍历字符串字面量的每个字符。以下是几种可行的实现方案:
方案1:固定长度字符串的预处理器实现
如果你处理的字符串长度固定(如示例中的9字符"test text"),可以直接编写对应长度的宏,预处理器会展开为你需要的初始化列表:
#define XOR(c, m) ((unsigned char)c ^ m) #define _MODIFY(str, mask) \ { \ XOR(str[0], mask), \ XOR(str[1], mask), \ XOR(str[2], mask), \ XOR(str[3], mask), \ XOR(str[4], mask), \ XOR(str[5], mask), \ XOR(str[6], mask), \ XOR(str[7], mask), \ XOR(str[8], mask), \ 0 \ }
使用效果:
_MODIFY("test text", 10)会被预处理器展开为:
{ XOR('t',10), XOR('e',10), XOR('s',10), XOR('t',10), XOR(' ',10), XOR('t',10), XOR('e',10), XOR('x',10), XOR('t',10), 0 }
编译器会自动将't'^10这类表达式计算为对应数值(如116^10=126),最终生成的数组与你期望的形式完全等价。若需处理更长的字符串,只需添加更多XOR(str[N], mask)项即可。
方案2:任意长度字符串的编译时实现(GCC/Clang扩展)
如果需要处理任意长度的字符串,可利用GCC/Clang的复合字面量特性,编译器会在优化模式下将循环直接优化为常量初始化:
#define _MODIFY(str, mask) \ ({ \ static const char _src[] = str; \ char _dest[sizeof(_src)]; \ for (size_t _i = 0; _i < sizeof(_src); ++_i) { \ _dest[_i] = ((unsigned char)_src[_i] ^ mask); \ } \ _dest; \ })
说明:
- 该宏生成的复合字面量数组,在
-O2及以上优化级别下,编译器会完全消除循环,直接生成异或后的常量数组。 - 仅支持GCC、Clang等兼容GNU扩展的编译器。
方案3:纯预处理器通用实现(依赖Boost.Preprocessor)
若必须用纯预处理器实现任意长度字符串的拆分,可借助Boost.Preprocessor库来完成字符串的字符拆分与遍历:
#include <boost/preprocessor/seq/for_each.hpp> #include <boost/preprocessor/tuple/elem.hpp> #define XOR_OP(r, data, elem) ((unsigned char)elem ^ BOOST_PP_TUPLE_ELEM(2, 0, data)), #define _MODIFY(str, mask) \ { \ BOOST_PP_SEQ_FOR_EACH(XOR_OP, (mask), BOOST_PP_STRINGIZE_TO_SEQ(str)) \ 0 \ }
说明:
- Boost.Preprocessor会将输入的字符串字面量拆分为单个字符的序列,再逐个应用异或操作,最终生成完整的初始化列表。
- 需要引入Boost库,适合允许使用第三方库的开发场景。
内容的提问来源于stack exchange,提问作者PanJanek
相关产品推荐
相关产品推荐

