【问题标题】:Where does the word "dereferencing" come from?“取消引用”一词从何而来?
【发布时间】:2015-02-11 06:13:28
【问题描述】:

这个问题会从草稿N1570中提取信息,所以基本上是C11。

通俗地说,取消引用指针意味着将一元* 运算符应用于指针。文件草案中只有一处出现“取消引用”一词(没有“取消引用”的实例),它在脚注中:

102) [...]

在一元*取消引用指针的无效值中 运算符是一个空指针,一个不恰当地对齐的地址 指向的对象的类型,以及后面的对象的地址 生命周期结束

据我所知,一元 * 运算符实际上称为“间接运算符”,如 §6.5.3.2 所示:

6.5.3.2 地址和间接运算符

4 一元 * 运算符表示间接。 [...]

类似地,它在附件 §J.2 中被明确称为间接运算符:

——对象的值通过数组下标[]访问, 成员访问.−>,地址&,或间接* 运算符或 创建地址常量时的指针转换 (6.6)。

那么在 C 中谈论“解除引用指针”是否正确,或者这是否过于迂腐?术语从何而来? (由于§6.5.2.1,我可以将[] 称为“deferencing”)

【问题讨论】:

  • :O 出于纯粹的迷恋……为什么?
  • 那么我祝你一切顺利,虽然我非常感谢使用正确的命名法,但你的问题对我来说似乎非常挑剔。并不是说这是一件坏事,只是……我不明白
  • 在 C 中,一元 & 运算符就是我所说的 address-of 运算符。我绝对不会称它为“引用”运算符,因为引用是其他东西,在 C 中不存在。数组索引可用于取消引用指针,因为 somePointer[i] 等同于 *(somePointer + i)
  • @4rlekin 在基本层面上并不挑剔。您不妨放弃所有术语,将其称为 & 运算符,每个人都会..可能知道您的意思。
  • 我认为解除引用是它的作用而不是它的本质。它遵循英语逐渐将动词变成名词的趋势。它是一个间接运算符。它所做的是取消引用指针以获取指针指向的值。

标签: c pointers language-lawyer nomenclature


【解决方案1】:

K&R v1

如果看一下C 编程语言,在第一版(1978 年)中,使用了术语“间接”

例子

2.12 评估的优先级和顺序

[…]

第 5 章讨论 *(间接)和 &(地址)。

,

7.2 一元运算符

[…]

一元 * 运算符表示间接:表达式必须是指针,而 result 是一个左值,引用表达式指向的对象。

它也列在 INDEX 中,例如

* indirection operator 89, 187

第 5.1 节的更长摘录

5.1 指针和地址

      由于指针包含对象的地址,因此可以通过指针“间接”访问该对象。 假设 x 是一个变量,比如 int,而 px 是一个 指针,以某种尚未指定的方式创建。一元运算符 c 给出一个对象的地址,所以语句

px = &x;

x 的地址分配给变量 px; px 现在说 “指向”x。 & 运算符只能应用于变量 和数组元素; &(x+1 )&3 这样的结构是非法的。它 获取寄存器变量的地址也是非法的。

    一元运算符* 将其操作数视为最终目标之外的地址,并访问该地址以获取内容。因此 如果y 也是int

y = *px;

px 指向的任何内容分配给y。所以 序列

px = &x;
y = *px;

为 y 分配相同的值

y = x;

K&R v2

在第二版中,解除引用这个词出现了。

5.1 指针和地址

一元运算符*是间接或解引用运算符;当应用于指针时,它访问指针指向的对象。假设 x 和 y 是整数,而 ip 是指向 int 的指针。这个人工序列展示了如何声明指针以及如何使用 & 和 *:

[…]


以前的用法

然而,这个词比 ("much") 更老,如可以在例如

中看到

A survey of some issues concerning abstract data types, 1974。例如 pp24/25。这里在与 ALGOL 68、PASCAL、SIMULA 67 的连接中说明。

一种语言将指针转换为值的机制是 被称为“解除引用”,一种强制形式(稍后讨论)。考虑声明

 p := q;

根据 p 和 q 的类型,有几种可能的解释。

让 '@' 成为解引用运算符(即,如果 p 指向 j ,则 @p 与 j 相同)和 '#' 是一个引用操作(即如果 p 指向 j ,则 p 与 #j 相同)。这 下表显示了一种语言为执行 作业:

                       |                                         
                       |   type of p                             
                       |                                         
                       |   t         ref t     ref ref t . . .   
                       |                                         
        ---------------------------------------------------------
                       |                                         
           t           |  p←q        p←#q       p←##q            
                       |             @p←q       @p←#q            
                       |                        @@p←q            
type                   |                                         
of                     |                                         
q          ref t       |  p←@q       p←q        p←#q             
                       |             @p←@q      @p←q             
                       |                        @@p←@q           
                       |                                         
                       |                                         
           ref ref t   |  p←@@q      p←@q       p←q              
             .         |             @p←@@q     @p←@q            
             .         |                        @@p←@@q          
             .         |                                         
                       |                                         
                       |                                         

[…]


硬币

还有其他几个使用示例。我无法找到它的确切位置和时间(至少现在还没有)。 (至少 1974 年的论文很有趣。)


为了获得乐趣,查看邮件列表(例如 net.unix-wizards)通常也很有用。 example from Peter Lamb at Melbourne Uni(11/28/83)

取消引用 NULL 指针是白痴的另一个例子 编写“便携式”代码,但假设 THEIR 机器是 只有一个会运行它的人:那些设计过的人 带有二进制标头的 cpio。 即使在 VAX 上,取消引用 NULL 也会给你带来垃圾:当然,*(char *)NULL 和 *(short *)NULL 返回 0,但 *(int *)NULL 会给你 1024528128 !!!!.

[…]


Ed1。加法

没有提到“解除引用”,但仍然;有趣的是 Ritchie:The Development of the C Language ✝

这里也一直使用术语“间接”——但是/和/等等。语言之间的联系有些详细。因此,考虑到例如,该术语的使用很有趣。像上面提到的 1974 年的论文。

作为概念和语法的间接示例,例如第 12 页。

    语法上的意外导致了语言的复杂性。间接运算符,在 C 中拼写为 *,在语法上是一元前缀运算符,就像在 BCPL 和 B 中一样。这在简单表达式中效果很好,但在更复杂的情况下,需要括号来指导解析。

[…]

有两种影响发生。最重要的是,C 有一组相对丰富的描述类型的方法(例如,与 Pascal 相比)。像 C-Algol 68 这样富有表现力的语言中的声明,例如,描述了同样难以理解的对象,仅仅是因为对象本身很复杂。第二个影响归因于语法的细节。 C 中的声明必须以许多人难以理解的“由内而外”的风格阅读 [Anderson 80]。


在这个结合中,可能还值得一提 ANSI C89 并提及如下:

3.1.2.5 类型

指向 void 的指针不能被取消引用,尽管这样的指针可以转换为可以被取消引用的普通指针类型。

一元 * 运算符取消引用指针的无效值包括 一个空指针,一个地址与 指向的对象,或具有自动 执行对象所在的块时的存储持续时间 声明并且所有封闭的块都已终止。

(我现在必须重新阅读其中的一些文件。)

【讨论】:

    【解决方案2】:

    因为在 K&R C 的好时光里,该语言只通过值传递参数。所以指针被用来模拟一个通过引用传递参数。人们(错误地)谈到了引用一个变量来构造一个指向变量的指针。

    而指针的解引用是相反的操作。

    现在 C++ 使用不同于指针的真正引用,但仍然使用 dereference 这个词(即使它并不真正正确)。

    【讨论】:

    • 在 C 中,参数仍然只能通过值传递。 (C++ 是一种不同的语言,而不是问题所在。)
    • 我的意思是 C++ 仍然保持从 K&R C 的继承,而 dereference 这个词就是从这个继承而来的。
    • 当然。我的观点是,“在 K&R C 的美好时光”似乎暗示 C 在这方面发生了变化。它没有。无论如何,问题与 C++ 无关,因此 C++ 对这个词的使用似乎与问题无关。
    【解决方案3】:

    我不知道确切的词源,但是可以将指针值(在一般意义上,不是 C/C++ 特定的含义)视为“引用”内存中的另一个对象;也就是说,p 指的是 x。当我们使用p 来获取存储在x 中的值时,我们绕过了该引用,或者取消引用p

    【讨论】:

      【解决方案4】:

      Kernighan 和 Ritchie,C 编程语言,第 2 版,5.1:

      一元运算符 * 是间接或解引用运算符; [...] ''pointer to void'' 用于保存任何类型的指针,但不能自行取消引用。

      【讨论】:

      • 这并没有提供问题的答案。要批评或要求作者澄清,请在其帖子下方发表评论。
      • @MaxLeske 但这确实提供了答案——他们在那里使用了“取消引用”这个词!由于它是规范文本,我认为这就足够了。实际报价在上面的评论中。更新:我编辑了我的答案并再次添加了实际报价,就像 SO 政策一样。
      • 我明白这一点。但是当我查看您的答案时,它唯一的内容是书名。您的修改确实使您的答案更有价值。
      • @MaxLeske 我不同意。对于此处发布的问题,这确实是一个有效的权威答案。
      猜你喜欢
      • 1970-01-01
      • 2015-01-12
      • 2010-11-10
      • 2011-01-27
      • 2011-02-14
      • 2019-10-28
      • 1970-01-01
      • 2017-10-12
      • 2019-05-07
      相关资源
      最近更新 更多