scanf在传递字符和整数说明符时做什么?
出于练习的目的,我得到了一段代码,并被告知找到bug。我消除了一堆噪音,让我绊倒的部分如下:scanf在传递字符和整数说明符时做什么?,c,scanf,C,Scanf,出于练习的目的,我得到了一段代码,并被告知找到bug。我消除了一堆噪音,让我绊倒的部分如下: int main() { char *p; char n; scanf("%i", n); if (n < get_int()) { p = malloc(n); } } intmain(){ char*p; 字符n; scanf(“%i”,n); if(nscanf()不尝试更改n,它使用n(按值传递)的副本 通常的s
int main() {
char *p;
char n;
scanf("%i", n);
if (n < get_int()) {
p = malloc(n);
}
}
intmain(){
char*p;
字符n;
scanf(“%i”,n);
if(n
在这里,如果我为n
输入一个数字,我会得到一个seg故障。如果输入字符,n
设置为0
。scanf的scanf
是如何做到这一点的
编辑:我想找出的练习是来自的练习2,它只是UB
C在这里没有指定任何特定的行为<代码>%i“需要int*
,而不是未初始化的char
转换为int
“scanf是如何做到这一点的?”暗示了明确的行为。没有指定的UB
“如果输入字符,n设置为0。”-->
scanf()
不尝试更改n
,它使用n
(按值传递)的副本
通常的scanf()
用法如下所示,其中传递nn
的地址,而不是nn
本身
int nn;
if (scanf("%i", &nn) == 1) Success();
else Failure();
您不仅向scanf传递了错误类型的变量,还传递了它的值,而不是指向它的指针。scanf无法知道这个值不是用来存储扫描数据的实际指针,所以这正是它要做的,扫描输入并将其放入n(视为指针值)碰巧指向的任何内存地址。在绝大多数情况下,这将尝试访问未映射/受保护/etc内存,并导致segfault/访问冲突
输入字符只是提前终止扫描,避免SEGFULT,并保持n完整。位由于n的值没有初始化,它可能恰好是任何东西,任何在该时间点出现在堆栈上的垃圾。
scanf是如何做到这一点的?
如果(输入是一个数字){*(int*)n=that_number;}else返回代码>第一个scanf(“%i”,n)代码>必须是scanf(“%i”、&n)
和第二个n必须是int
而不是char
,否则您的行为未定义。然后,如果不输入数字,则n不是由scanf初始化的,其返回值为0而不是1,除非您检查返回值,否则无法正确使用scanf()
。例如,if(scanf(“%i”,&n)!=1){/*handle error*/}
关于n
如果您检查手册页中的scanf()
和%i”
转换说明符“下一个指针必须是指向int的指针”
@code>则与此代码类似,您在所有情况下都有未定义的行为(无论您的输入如何)再也没有比这更重要的了say@DavidC.Rankinscanf不会在n中写入,除非它的未初始化值(也从中读取)奇迹般地是它的地址;)没有“&”