数组作为 scanf 的函数参数。地址运算符

Arrays as scanf's function arguments. Adress operator

#include <stdio.h>

int main(void)
{
  char s[32];

example_1:
  scanf("%s", s);
  printf("%s\n", s);

example_2:
  scanf("%s", &s[0]);
  printf("%s\n", s);

example_3:
  scanf("%s", &s);
  printf("%s\n", s);
}
  1. 为什么#3 的工作方式与其他 2 相同?

  2. #3 是否有效?为什么?

  1. 变体一依赖于 array decay,因此有效。

    (在大多数情况下,数组衰减为指向其第一个元素的指针,例外情况是:Address-of (&s)、sizeof s_Alignas(s)_Alignof(s)。 )

  2. 变体二执行数组衰减将手动执行的操作,但更冗长,因此更糟。

  3. 变体三严格来说是 Undefined Behavior,尽管它恰好适用于大多数实现。
    症结在于 &s 在默认促销后不是 char* 类型,尽管它指向正确的地址。

似乎工作是UB中最奸诈的子集。

虽然三者的类型不同:

  • s 是一个 char[32](32 个 char 的数组),它在需要的地方透明地衰减到 char*
  • &s[0] 是一个 char*(指向 char 的指针)
  • &s是一个char(*)[32](指向32个chars的数组的指针)

它们都解析为相同的值(字符数组的起始地址)。因此,当将它传递给 printf 时,它期望 char*,所有 3 个的结果都相同(假设 char(*)[32] 的对象表示与 char(*)[32] 的对象表示相同=13=],这取决于实现,但通常是这种情况)。

虽然只有前两个有效 - 第三个只是偶然工作。