在这里,我编写了下面的代码来解析十六进制字符串并将其转换为十进制格式。在scanf
中,我添加了char
类型变量来存储由格式说明符%[n]
解析的用于调试程序的内容。
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
int main(){
int a;
char c;
while(true)
{
if(scanf("%i%1[n]", &a, &c) != EOF)
{
printf("a = %d; c = %d", a, c);
}
else
{
break;
}
}
}
当我运行编译后的执行test_scanf
时,我得到
$./test_scanf
0xff
a = 0; c = 10
根据我的理解,%i
将匹配0xff
,%1[n]
将匹配n
(输入中没有显示)。因此,结果将是a = 255; c = 10
。那么到底出了什么问题呢?
注:我在Linux上运行这个代码。
您正在调用未定义行为,因为%1[n]
向给定地址写入2个字节,但您传递给它的地址只有一个空间。
实际上,可能发生的情况是,正在写入&c
的n
覆盖了堆栈中a
的内容。但不值得对未定义行为进行推测。任何事情都有可能发生。避免它。使用char c[2]
代替char c
。(并适当地修复对scanf
的调用)
"%1[n]"
中的1
是宽度限制,最多读取1个字符并保存在&a
中
时,"%1[n]"
形成字符串。不幸的是,目的地只有一个空间——导致未定义行为(UB)。
"%1[n]"
不读取任何内容,也不附加空字符,如果第一个字符不是'n'
。扫描停止。不匹配的输入保留在stdin
.
最好测试scanf()
所需的转换数量,而不是测试EOF
。
// char c;
char c[2];
while(true) {
// if(scanf("%i%1[n]", &a, &c) != EOF) {
if(scanf("%i%1[n]", &a, c) == 2) {
printf("a = %d; c = %d", a, c);
} else {
break;
}
}