ubt*_*tac 2 c types scanf strtol
我正在将一个mac地址的字符串表示转换为一个UINT8定义为的数组unsigned char.我好奇为什么当我读入常规32位s 的数组时读入s和实际值sscanf()的数组时会读取全0 .它几乎就像是砍掉了int的错误结束的8位.UINT8int
char *strMAC = "11:22:33:AA:BB:CC";
typedef unsigned char UINT8;
UINT8 uMAC[6];
int iMAC[6];
sscanf( (const char*) strMac,
"%x:%x:%x:%x:%x:%x",
&uMAC[0], &uMAC[1], &uMAC[2], &uMAC[3], &uMAC[4], &uMAC[5] );
printf( "%x:%x:%x:%x:%x:%x",
uMAC[0], uMAC[1], uMAC[2], uMAC[3], uMAC[4], uMAC[5] );
// output: 0:0:0:0:0:0
sscanf( (const char*) strMac,
"%x:%x:%x:%x:%x:%x",
&iMAC[0], &iMAC[1], &iMAC[2], &iMAC[3], &iMAC[4], &iMAC[5] );
printf( "%x:%x:%x:%x:%x:%x",
iMAC[0], iMAC[1], iMAC[2], iMAC[3], iMAC[4], iMAC[5] );
// output: 11:22:33:AA:BB:CC
Run Code Online (Sandbox Code Playgroud)
更新:%hhx将适用于C99及以上,但我有一个旧的代码库,所以我最终得到strtoul():
char *str = strMac;
int i = 0;
for(i = 0; i < 6; i++, str+=3) {
uMAC[i] = strtoul(str, NULL, 16);
}
Run Code Online (Sandbox Code Playgroud)
TL; DR - 由于参数类型不匹配,第一个片段会调用UB.
详细说明,引用%x格式说明符的参数类型的要求,从C11标准的章节§7.21.6.2,fscanf()函数,(强调我的)
x匹配可选的带符号十六进制整数,其格式与strtoul()函数的主题序列的预期相同,其值为16.相应的参数应该是指向无符号整数的指针.
所以,在使用时
sscanf( (const char*) strMac,
"%x:%x:%x:%x:%x:%x",
&uMAC[0], &uMAC[1], &uMAC[2], &uMAC[3], &uMAC[4], &uMAC[5] );
Run Code Online (Sandbox Code Playgroud)
在你的代码中,你提供了错误的参数类型%x.根据标准,再次,
[...].除非由a指示赋值抑制,否则
*转换的结果将放在由尚未收到转换结果的format参数后面的第一个参数指向的对象中.如果此对象没有适当的类型,或者无法在对象中表示转换结果,则行为未定义.
因此,提供错误类型作为参数是调用 未定义的行为.
解:
为了表示你要提供一个(符号或无符号)char输入参数,你需要使用前面带格式说明hh长度修改,如%hhx与scanf()家人.