C/C++之前的编程语言是否有指针?

5

旧语言(如Fortran(Fortran-90之前的版本)、cobol或pascal)中是否有指针使用?如果没有,那这些语言是如何实现指针在今天高级语言中所使用的功能的呢?

而且由于Java中不存在指针,是否有其他方式来复制指针所完成的工作呢?


Pascal确实有指针,类似于p^,你可以通过数组和索引完成所有操作。无法抵制,所以进行编辑:正如所有真正的程序员所知道的那样,唯一有用的数据结构是数组。字符串、列表、结构体、集合——这些都是数组的特例,可以同样轻松地进行处理,而不会在编程语言中引入各种复杂性。高级数据类型最糟糕的事情就是你必须声明它们 - bestsss
1
@Lundin,当然可以处理单独的字节/单词/块,它们只是乱序的。想象一下,如果你需要contains(xxx)或hash()/sum(),你不必按顺序连续访问数组以获得正确的结果。链接属性只有在需要数据排序时才有趣(虽然这是通常情况,但仍然如此)。关键是:即使没有排序索引,数组仍然很有用。至于数组的定义:我想它对于一个RP来说可能太狭窄了 :) - bestsss
2
@Lundin:希望你能够实现一个基于数组的链表,因为你的整个内存空间就是由字节数组构成的。 - Ben Voigt
@Ben 数组是编程中用于分配相邻内存的多个对象的定义。按定义,可以对其进行索引。您的原始程序内存不是任何高级语言的直接组成部分。CPU的内存映射可能也不包含相邻的项目,它们可能在内存空间的任何位置分配,其中间有非法地址。此外,物理内存单元/银行通常不允许跨越它们分配对象。还有对齐问题。最后还有堆,其中对象可以被分段分配,然后按定义不是数组。 - Lundin
@Lundin:你并没有帮助自己的情况。在具有多通道内存控制器的现代系统上,任何大于通道宽度的对象都可以跨多个银行进行分段(为了提高速度而进行分段)。这使用了多个银行、多个电路、多个其他东西。 - Ben Voigt
显示剩余6条评论
6个回答

7

Algol 68有类似于C/C++指针的引用。

Pascal有指针,但不能对其进行算术运算。

PL/I有指针。

在FORTRAN和COBOL中,你大多数情况下都没有像语言中写的动态分配这样的东西。我曾经在FORTRAN中编写过一些使用数组的链表代码,其中数组索引作为“下一个”项的链接(即x[1]是数据项,x[2]是其链接到下一个数据项,x[3]是另一个数据项,依此类推)。称之为“笨拙”几乎是过于慷慨了。


1
我在大学里上的数据结构课是用Fortran 77教授的,我们使用数组来实现列表、栈和树结构。虽然不太有趣,但那时我们都不想碰C语言(我们的程序刚从Pascal转换过来,而且没有任何教授或助教有足够的C语言经验来正确地教授它)。 - John Bode
@Jerry:这有什么“笨拙”的?去掉数组的强类型,增加数组以填充虚拟内存,你剩下的就是一个“普通”的链表。 - Ben Voigt
@John,真遗憾,你破坏了它 x.x - bestsss
@Ben Voigt:这完全是真的,但使用起来仍然很笨拙。 - Jerry Coffin
@Jerry:我认为实现相同功能的更合理的方法是 x[1] 是一个数据项,x[x[1]] 是下一个项,x[x[x[1]]] 是第三个项。我认为这就是FAT文件系统查找簇链的方式。 - Ben Voigt
显示剩余7条评论

3

BCPL中有构造 a*[b](在我们的实现中可以简化为 a!b,这是一个运行在3B2 UNIX系统上的6809嵌入式系统编译器),它相当于C语言中的 a[b]。当然,BCPL只有单词的概念,没有C语言中更多的结构等功能。

a!b 是从单词地址偏移的单词偏移量,但我们使用的实现还提供了选项,可以从单词地址的字节偏移 a!%b 和从字节地址的字节偏移 a%%b


你确定你没有把BCPL和其他语言混淆了吗?根据我手头的Richards' BCPL手册,可以通过v*[42]访问向量的元素。 - Christoph
有趣的是,@Christoph,a!b 在我们的实现中也必须是一个扩展(就像 !%%% 一样)。因为那是我唯一使用过的 BCPL,所以我认为它是基本语言的一部分。已调整答案以反映这一点。 - paxdiablo
您可以在http://www.fh-jena.de/~kleine/history/找到BCPL(以及其他语言)参考手册的PDF版本;网络上还有另一个PDF版本-然而,该版本已经被OCR处理过,导致一些混淆和有时微妙的错误(Rvalue <-> Lvalue)。 - Christoph

0
指针所代表的功能自计算机机器语言诞生以来就一直存在,因此编程语言始终允许某种形式的访问功能,即使不像指针那样普遍。我记得曾经咨询过将一些K&R C代码移植到Fortran 66的工作。C代码中充满了指向结构体的指针,这在Fortran 66中没有任何特性可以很好地映射。

假设C代码有以下结构体:

struct datastruct { int ival; float fval; } data[100];

Fortran映射使用了一个公共块(我不确定格式是否正确,我的Fortran 66已经非常陈旧):

COMMON /DATASTRUCT/ IVAL(100), FVAL(100)

C中的一个函数只需要接收一个指向结构体的指针,无需知道该结构体是来自数组还是malloc'ed或其他什么:

float func(struct datastruct *sp) { return sp->ival * sp->fval; }

当映射到Fortran 66时,“结构体”都只是包含在公共块中的数组索引:

FUNCTION FUNC(INDEX)
COMMON /DATASTRUCT/ IVAL(100), FVAL(100)
RETURN IVAL(INDEX) * FVAL(INDEX)

虽然不像指针那样优雅,但在当年的CDC 7600上完成了工作。


0
不要忘记 ADA(和 VHDL)的访问类型。汇编和(哇)机器代码支持间接寻址,尽管没有指针类型,但一切都在使用中。

汇编和(惊讶)机器码支持间接寻址,这让我想起了6502,其中“指针”在代码中是通过绝对索引来实现的,因为零页+Y间接寻址受限(由于可用字节非常少)。 - bestsss

0
在这些编程语言中,可以通过引用或值传递参数给函数。通过引用传递参数意味着将指针传递给该函数。现代语言如C#和Visual Basic也采用了这种方式。

引用不允许进行任何指针算术运算。引用最好被描述为指针的有限子集。顺便说一句,Visual Basic不是现代语言。 - Lundin
@Lundin: 这基本上是将 C++ 指针和引用的实现作为这些术语本身的定义。Pascal 指针不支持算术运算。Algol 68 中的引用与 C++ 指针比起来更接近于 C++ 引用。 - Jerry Coffin
可能只是定义的问题,因为现代语言(如C#和Java)与C++使用引用的方式相同。 - Lundin
@Lundin:不,它们不能。C++引用无法重新绑定。C#和Java中的引用可以重新绑定。 - Ben Voigt
标准/经典的Pascal不支持,几乎所有32/64位生产编译器都支持。 - Marco van de Voort

0

Lisp是一种在1950年代发明的语言,具有指针。实际上,在Lisp中,指针是数据管理的核心。"Lisp"是"List Processor"的缩写,而列表是(也是)Lisp中的链接列表。这可能是最早使用指针作为构建块的语言之一。

在大多数Lisp方言中,列表元素由两个项目组成。一个是原始数据元素,如数字,或指向此元素的最年长子项的指针。第二个元素是指向此元素的下一个兄弟的指针。可以从这些元素构建任意复杂度的树形或图形结构。

Lisp的第一个实现都具有自动垃圾收集功能。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接