为什么可以将双指针(地址的地址)传递给 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 错误,这些错误很难追踪。