c++ - char a[] 的语义

标签 c++ c pointers semantics

我最近在向同事解释原因时让自己感到尴尬

char a[100];
scanf("%s", &a); // notice a & in front of 'a'

非常糟糕,稍微好一点的方法是:

char a[100];
scanf("%s", a); // notice no & in front of 'a'  

好的。对于每个准备告诉我为什么出于安全原因无论如何都不应该使用 scanf 的人:放轻松。这个问题其实是关于“&a”和“a”的意思。

问题是,在我解释了它为什么不起作用之后,我们尝试了它(使用 gcc)并且它起作用了 =))。我跑了一个快速

printf("%p %p", a, &a);

它会打印两次相同的地址。

谁能给我解释一下这是怎么回事?

最佳答案

嗯,&a 的情况应该很明显了。您完全按照预期获取数组的地址。 a 有点微妙,但答案是 a 数组。并且正如任何 C 程序员都知道的那样,数组往往会在最轻微的刺激下退化为指针,例如在将它作为函数参数传递时。

所以 scanf("%s", a) 需要一个指针,而不是数组,所以数组退化为指向数组第一个元素的指针。

当然 scanf("%s", &a) 也可以,因为这是数组的明确地址。

编辑: 哎呀,看起来我完全没有考虑 scanf 实际期望的参数类型。这两种情况都会产生一个指向相同地址但类型不同的指针。 (指向字符的指针,而不是指向字符数组的指针)。

我很乐意承认我对省略号 (...) 的语义了解不够,我一直像瘟疫一样避免这种情况,所以看起来转换为 scanf 最终使用的任何类型都可能是未定义的行为。阅读评论和 litb 的答案。你通常可以相信他能把这些东西做好。 ;)

关于c++ - char a[] 的语义,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/496226/

相关文章:

c++ - C++中的小型可读方案解释器?

c++ - 为什么无堆栈协程需要动态分配?

c++ - 在析构函数 C++ 中删除指针

c++ - 如何让 C++ 从 USB 端口(如串行端口)执行 I/O

c++ - 在mysql服务器源代码中找不到 'ib_lock_t'的定义

c - 为什么我输入两次 't' 时得到的是垃圾值?

c - OCaml 使用字节码编译器从 C 函数返回未装箱的 float

c - 为什么我的 Makefile 在 Mac 上找不到 OpenSSL?

c++ - 编译器如何确定它正在寻址哪种多态类型

c - 如何在C中返回一个二维指针?