【发布时间】:2021-11-26 09:33:20
【问题描述】:
我偶然发现了一个关于这段代码的问题
int arr[10];
scanf("%s", arr);
printf("%s", arr);
我不知道其目的,但我完全知道这段代码有多么难闻。但我的问题是这是否合法,如果我可以期望它重新打印我输入的字符串? (前提是输入的字符串不是太长导致缓冲区溢出)
我还想知道是否有任何实际有用的示例。
来自关于fprintf的C标准https://port70.net/%7Ensz/c/c11/n1570.html#7.21.6.1p8
如果不存在 l 长度修饰符,则参数应为指向字符类型数组的初始元素的指针。
和 fscanf https://port70.net/%7Ensz/c/c11/n1570.html#7.21.6.2p12
如果没有 l 长度修饰符,对应的参数应该是一个指向一个足够大的字符数组的初始元素的指针,它可以接受序列和一个终止的空字符,它将自动添加。
在这种情况下,它不是字符数组。但我似乎记得有一些关于与 char 指针的隐式转换的特殊规则,但我也记得这些不适用于可变参数函数。
【问题讨论】:
-
它的形式是 UB,但如果 scanf 只是将指针转换为
char*(并且标准库被编译为标准 C,这绝不是必需的),那么它将起作用。跨度> -
可以通过在
scanf和printf参数中使用(char *)arr使其合法化。但请注意,scanf可能会将arr的int元素设置为陷阱表示,这可能会导致在读取int元素时引发实现定义的信号。 -
@TomKarzes 你可能是整个历史上第一个犯这个错误的程序员;)
标签: c printf scanf language-lawyer