【问题标题】:Where am I going wrong about this reasoning?这个推理我哪里错了?
【发布时间】:2018-07-18 07:57:30
【问题描述】:

考虑在C中定义一个char指针。那么指令:

char *str
str = "Hello World!"

没有产生任何错误。假设我对 C 和指针的了解勉强可以接受,为什么这条指令是正确的?不应该是:

str = &("Hello World!");

【问题讨论】:

  • @Jabberwocky "Hello world" 是一个char 数组,在大多数情况下会衰减为一个指针,但可以与sizeof 区分。
  • 以上行肯定会产生多个错误。由于各种原因,这不是有效的 C,(旁注 - 短语:C 没有说明。你可能意味着语句,但第一行也不是语句。即使我们认为你只是忘记了分号。

标签: c pointers dereference


【解决方案1】:

引用C11,第 6.3.2.1 章

除非它是sizeof 运算符、_Alignof 运算符或 一元 & 运算符,或者是用于初始化数组的字符串文字,该表达式具有 type ''array of type'' 被转换成一个类型为 ''pointer to type'' 的表达式,它指向 到数组对象的初始元素并且不是左值。 [....]

这里,字符串字面量,基本上是charFootNote 类型的数组,作为赋值运算符的RHS,衰减到指向数组第一个元素的指针。

因此,LHS(指针类型)和 RHS(派生指针类型)是兼容的,符合赋值运算符的要求,并且语句有效。

也就是说,

 str = &("Hello World!");

无效,因为&("Hello World!"); 的类型为char (*) [13](指向13 个chars 的数组的指针),并且不是char * 的兼容类型,即赋值的LHS。


脚注:

引用C11, §6.4.5

在翻译阶段 7,一个字节或零值代码被附加到每个多字节 由一个或多个字符串文字产生的字符序列。78) 多字节字符 然后使用序列来初始化一个静态存储持续时间和长度的数组 足以包含序列。对于字符串文字,数组元素有 类型 char,并使用多字节字符的各个字节进行初始化 顺序。 [....]

【讨论】:

    【解决方案2】:

    字符串文字"Hello World!"char [13] 类型的匿名对象,即13 个字符的数组,它在所有上下文中隐式衰减为指向数组第一个字符(char *!)的指针,除非当数组作为 & 或 sizeof/_Alignof 的操作数出现。

    str = &("Hello World!")
    

    (可以不带括号 str = &"Hello World!" 编写)特别正确,因为 &("Hello World!") 的结果是 *char (*)[13] 类型,即指向 13 个字符的数组的指针!

    GCC 会将此诊断为

    test.c:3:9: warning: assignment from incompatible pointer type [-Wincompatible-pointer-types]
         str = &"Hello World!";
    

    【讨论】:

      猜你喜欢
      • 2021-03-04
      • 1970-01-01
      • 2010-10-12
      • 2011-07-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-01-21
      相关资源
      最近更新 更多