Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/63.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
为什么在使用指针指向指针时scanf正常工作?_C_Pointers - Fatal编程技术网

为什么在使用指针指向指针时scanf正常工作?

为什么在使用指针指向指针时scanf正常工作?,c,pointers,C,Pointers,我想知道为什么这个代码可以工作。我假设scanf正在将值分配给指向char的指针的地址。我知道这个表达式没有定义,但是为什么printf使用指针可以打印正确的值呢 int main() { char* p; p = (char*)malloc(sizeof(char)); scanf("%c", &p); printf("%c", p); return 0; } 结果是 c c 使用scanf(),将一个字节(相当强制地)存储到一个多字节的变量

我想知道为什么这个代码可以工作。我假设
scanf
正在将值分配给指向
char
的指针的地址。我知道这个表达式没有定义,但是为什么
printf
使用指针可以打印正确的值呢

int main() {
    char* p;
    p = (char*)malloc(sizeof(char));
    scanf("%c", &p);
    printf("%c", p);
    return 0;
}
结果是

c
c
使用
scanf()
,将一个字节(相当强制地)存储到一个多字节的变量中(
sizeof(char*)
,在64位机器上可能是8个字节)。使用
printf()
,然后读取此变量的一个字节(
sizeof(char)
,始终是标准的一个字节),并打印它。变量
p
的空间大于存储
char
所需的空间。由于大小不一致,您无法确定
printf()
将读取
p
的哪个字节。它可能是
scanf()
写入的字节,也可能是垃圾数据。幸运的是,
printf()
读取了
scanf()
写入的相同字节

如果这一切听起来有点不确定,那是因为它涉及到未定义的行为。您不正确地使用了
scanf()
printf()
,因此他们无法保证会发生什么。简而言之,不要这样做


printf()
scanf()
不对作为参数给定的源/目标执行任何特殊类型检查。他们使用奇特的指针算法和堆栈上的参数来计算需要在哪里读/写东西。编译器编译后,
printf()
scanf()
不会抱怨。编译器应该警告您,给定的参数类型与格式字符串不匹配。如果没有,您可能有一个坏的/旧的编译器,或者应该使用命令行选项启用更多警告
-Wall

p
是一个包含内存地址的变量,内存地址肯定大于1字节。如果在此变量中存储char值,则先前的值(malloc’ed内存块)将丢失
printf
只需将变量作为
char
变量处理并打印其内容。如果您怀疑char将存储在malloc获得的内存块中,那么不,它不是

试试这个:

int main() {
    char *p, *q;
    p = q = (char*)malloc(sizeof(char));
    scanf("%c", &p);
    printf("%c\n%c\n", p, *q);
    return 0;
}

为了有助于解释其他答案,您似乎打算做以下工作-比较差异,然后再看看其他答案,看看这是否有帮助,因为我不确定您是否清楚代码中发生了什么

int main() {
    char* p = malloc(sizeof(char));
    scanf("%c", p);
    printf("%c", *p);
    return 0;
}

因为
printf
不分配任何内容。“似乎有效”是未定义行为的一种可能表现形式。我很惊讶您没有收到编译器警告。如果不是,你应该考虑使用<代码>墙>代码>。请在C和C++之间选择一个好的地方:<代码> MARROCKE()/<代码>内存。什么
scanf()
存储它存储在堆栈上的局部变量
p
中。因此,即使类型不同,它也可能打印正确的值?我知道我不应该这样做,我只是想知道为什么这段代码会起作用。我试着用这个答案解释它:你将数据存储在比需要大的地方,然后从同一个容器中读取一些内容。你很幸运,结果是你所期望的。从技术上讲,这是行不通的。你只是碰巧看到了同样的结果,如果它真的起作用的话。