数组作为 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);
}
为什么#3 的工作方式与其他 2 相同?
#3 是否有效?为什么?
变体一依赖于 array decay,因此有效。
(在大多数情况下,数组衰减为指向其第一个元素的指针,例外情况是:Address-of (&s
)、sizeof s
、_Alignas(s)
和 _Alignof(s)
。 )
变体二执行数组衰减将手动执行的操作,但更冗长,因此更糟。
变体三严格来说是 Undefined Behavior,尽管它恰好适用于大多数实现。
症结在于 &s
在默认促销后不是 char*
类型,尽管它指向正确的地址。
似乎工作是UB中最奸诈的子集。
虽然三者的类型不同:
s
是一个 char[32]
(32 个 char
的数组),它在需要的地方透明地衰减到 char*
&s[0]
是一个 char*
(指向 char
的指针)
&s
是一个char(*)[32]
(指向32个char
s的数组的指针)
它们都解析为相同的值(字符数组的起始地址)。因此,当将它传递给 printf
时,它期望 char*
,所有 3 个的结果都相同(假设 char(*)[32]
的对象表示与 char(*)[32]
的对象表示相同=13=],这取决于实现,但通常是这种情况)。
虽然只有前两个有效 - 第三个只是偶然工作。
#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);
}
为什么#3 的工作方式与其他 2 相同?
#3 是否有效?为什么?
变体一依赖于 array decay,因此有效。
(在大多数情况下,数组衰减为指向其第一个元素的指针,例外情况是:Address-of (
&s
)、sizeof s
、_Alignas(s)
和_Alignof(s)
。 )变体二执行数组衰减将手动执行的操作,但更冗长,因此更糟。
变体三严格来说是 Undefined Behavior,尽管它恰好适用于大多数实现。
症结在于&s
在默认促销后不是char*
类型,尽管它指向正确的地址。
似乎工作是UB中最奸诈的子集。
虽然三者的类型不同:
s
是一个char[32]
(32 个char
的数组),它在需要的地方透明地衰减到char*
&s[0]
是一个char*
(指向char
的指针)&s
是一个char(*)[32]
(指向32个char
s的数组的指针)
它们都解析为相同的值(字符数组的起始地址)。因此,当将它传递给 printf
时,它期望 char*
,所有 3 个的结果都相同(假设 char(*)[32]
的对象表示与 char(*)[32]
的对象表示相同=13=],这取决于实现,但通常是这种情况)。
虽然只有前两个有效 - 第三个只是偶然工作。