为什么在使用指针指向指针时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
中。因此,即使类型不同,它也可能打印正确的值?我知道我不应该这样做,我只是想知道为什么这段代码会起作用。我试着用这个答案解释它:你将数据存储在比需要大的地方,然后从同一个容器中读取一些内容。你很幸运,结果是你所期望的。从技术上讲,这是行不通的。你只是碰巧看到了同样的结果,如果它真的起作用的话。