sscanf使用%i格式符转换字符串为何自动识别八进制数值?
问题原因
这是C标准中sscanf函数%i格式符的默认规则导致的:%i在解析整数字符串时会自动判定基数,判定逻辑如下:
- 若字符串以
0x或0X开头,按十六进制解析 - 若字符串以单个
0开头(后面没有x/X),按八进制解析 - 其余情况按十进制解析
你传入的字符串00000000041以多个前导0开头,匹配八进制解析规则,八进制的41转换为十进制正好是33,和你得到的返回结果一致。
修复方案
如果你需要强制将字符串按十进制解析,忽略前导0的特殊含义,只需要把格式符从%i替换为%d(对应有符号int)或者%u(对应无符号unsigned int)即可,这两个格式符只会将输入按十进制处理,不会识别八进制、十六进制前缀。
你提供的代码还有2处可优化的点:
- 函数返回值为
unsigned int,但存储结果的变量res是int类型,存在符号不匹配的溢出风险,建议将res的类型改为unsigned int,同步将格式符改为%u sscanf的返回值是成功匹配并赋值的参数个数,只有发生读取错误时才会返回EOF(即-1),如果输入完全不匹配数字会返回0,你原来的判断条件== -1会漏掉这种异常场景,建议改为判断返回值是否等于1:
unsigned int formatInt(char *ptr) { unsigned int res; if (sscanf(ptr, "%u", &res) != 1) exit(-1); return res; }
内容的提问来源于stack exchange,提问作者0xRyN
相关产品推荐
相关产品推荐

