为什么可以将双指针(地址的地址)传递给 scanf?
Why is it possible to pass a double pointer (address of address) to scanf?
这段简单的代码正是我所期望的:
#include <stdio.h>
int main()
{
char input[20];
printf("enter a string: ");
scanf("%[^\n]s", input);
printf("input: %s\n", input);
}
其中 input
是 (char*)[20]
。但是为什么我可以通过这个:
#include <stdio.h>
int main()
{
char input[20];
printf("enter a string: ");
scanf("%[^\n]s", &input);
printf("input: %s\n", input);
}
它仍然可以编译和运行?传递的参数 &input
应该是 (char**)[20]
这不应该是正确的,但它运行了。为什么?
在您的代码中,表达式 input
(当用作 scanf
的参数时)将求值(即 decay)为 20-字符数组和表达式 &input
将计算为数组本身的地址 - 这将是相同的,在本例中为 。这可以通过在您的代码中添加如下一行来证明:
printf("%p %p\n", (void*)(input), (void*)(&input)); // Print the two addresses - SAME!
因此,您对 scanf
的调用实际上会传递正确的值(输入缓冲区的地址)。
但是,一个好的编译器会警告您不兼容的指针类型;例如,clang-cl 生成这个:
warning : format specifies type 'char *' but the argument has type
'char (*)[20]' [-Wformat]
当然,您是要解决还是忽略警告,这取决于您;但是,在更复杂的代码中,这样的 'mistakes' 会导致 运行-time 错误,这些错误很难追踪。
这段简单的代码正是我所期望的:
#include <stdio.h>
int main()
{
char input[20];
printf("enter a string: ");
scanf("%[^\n]s", input);
printf("input: %s\n", input);
}
其中 input
是 (char*)[20]
。但是为什么我可以通过这个:
#include <stdio.h>
int main()
{
char input[20];
printf("enter a string: ");
scanf("%[^\n]s", &input);
printf("input: %s\n", input);
}
它仍然可以编译和运行?传递的参数 &input
应该是 (char**)[20]
这不应该是正确的,但它运行了。为什么?
在您的代码中,表达式 input
(当用作 scanf
的参数时)将求值(即 decay)为 20-字符数组和表达式 &input
将计算为数组本身的地址 - 这将是相同的,在本例中为 。这可以通过在您的代码中添加如下一行来证明:
printf("%p %p\n", (void*)(input), (void*)(&input)); // Print the two addresses - SAME!
因此,您对 scanf
的调用实际上会传递正确的值(输入缓冲区的地址)。
但是,一个好的编译器会警告您不兼容的指针类型;例如,clang-cl 生成这个:
warning : format specifies type 'char *' but the argument has type 'char (*)[20]' [-Wformat]
当然,您是要解决还是忽略警告,这取决于您;但是,在更复杂的代码中,这样的 'mistakes' 会导致 运行-time 错误,这些错误很难追踪。