如何在C语言u"..."字符串中构造故意UTF-16编码错误
问题原因
C语言标准明确规定,u"..." 类型的char16_t字符串字面量中,不允许直接使用\uXXXX形式的转义写入UTF-16代理区码点(U+D800 ~ U+DFFF区间),编译器在语法校验阶段就会判定这类转义为非法通用字符名,直接抛出编译错误,因此无法通过直接写\ud800这类转义的方式构造包含非法UTF-16编码的测试字符串。
另外原测试代码的注释有误:0xd800属于高代理项,不是低代理项。
可行构造方法
方法1:直接用char16_t数值数组构造(最稳妥、可移植性最高)
非法UTF-16序列本质就是不符合编码规则的16位整数序列,你可以直接按数值写数组,末尾补0x0000作为终止符,和普通u"..."生成的字符串内存布局完全一致,可以直接传入解码函数测试:
#include <uchar.h> // 未匹配高代理项测试用例 const char16_t test_unmatched_high_surrogate[] = {0xd800, 0x0000}; // 代理顺序颠倒测试用例(低代理在前、高代理在后) const char16_t test_reversed_surrogate[] = {0xdc01, 0xd802, 0x0000};
这种写法完全绕开了编译器对Unicode转义的合法性校验,不存在兼容问题,是构造错误编码测试用例的首选方案。
方法2:使用十六进制转义\x替代\u转义
编译器不会对\x开头的十六进制转义做Unicode编码合法性校验,你可以直接把代理项的码值写成\x转义形式,放在u"..."字面量中:
// 未匹配高代理项 const char16_t* test_unmatched = u"\xd800"; // 顺序颠倒的代理对 const char16_t* test_reversed = u"\xdc01\xd802";
使用这个方法需要注意:\x转义会贪婪匹配后面所有连续的十六进制字符,如果转义后面紧接其他十六进制字符(0-9、a-f、A-F),需要用字符串字面量拼接截断转义范围,比如要写0xd800后面跟字符'a',要写成u"\xd800""a",避免编译器把'a'也当成转义值的一部分。
注意事项
*不要试图用宏拼接、字符替换等取巧方式绕过编译器对\u转义的校验,这种用法违反C语言标准,不同编译器、不同编译选项下的行为不可预期,没有可移植性。
内容的提问来源于stack exchange,提问作者fuz
相关产品推荐
相关产品推荐

