scanf在传递字符和整数说明符时做什么?

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

出于练习的目的,我得到了一段代码,并被告知找到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(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中写入,除非它的未初始化值(也从中读取)奇迹般地是它的地址;)没有“&”