我们需要指针吗?

4

是否存在需要使用指针的情况或具体示例?例如,某些需要指针才能完成的任务可否不使用它们来实现?我们可以将指针作为函数参数发送,但这也可以通过返回数据来完成。在函数中使用指针可以更改多个变量,但是也有一种解决方法。

我们真的需要指针吗?

我知道这是个愚蠢的问题,抱歉,但在这种情况下似乎对我来说是正确的。我只想知道是否存在不能使用指针完成的事情。


9
我认为这是一个完全合理的问题。 - Puppy
6
这基本上是一个“让我帮你谷歌一下”的问题。我在Google上搜索“为什么需要指针?”就立刻找到了10个优秀的结果。不确定它是否适合在这里提问,但只需要稍微研究一下就可以轻松回答。 - Onorio Catenacci
2
@esej - 我更喜欢将磁带头视为指针 :) - Flexo
3
如果我们进入图灵泥潭,λ演算没有指针或磁带头。 - Logan Capaldo
3
很多都取决于定义。例如,在“指针”和“非指针”之间,你在哪里划线?相当多的数据结构需要某些东西来引用其他数据,但那不一定是像C或C++使用该术语的“指针”。 - Jerry Coffin
显示剩余11条评论
5个回答

5
指针可以在高级语言的范例设计中避免 - 以Java为例 - 但它们往往会在实际的功能实现中再次出现。除非您使用某种动态重新配置的FPGA架构、状态机集群或类似的计算机概念,否则实际的计算机设备并不是非常面向对象的。我们不在存储设备中执行操作,而是获取数据,在其上进行计算,并将其写回。要在内存中查找数据,我们使用地址的概念(虽然有一些称为内容寻址内存的东西,但对于大多数目的来说它们并不理想)。一旦您决定将数据(或函数体、包含两者的结构)存储在某个地址的内存中,就必须确定如何处理该地址。您可以将地址写入另一个内存位置,这就是最熟悉的指针概念。您可以将地址存储在堆栈上,但那只是相对于称为“堆栈指针”的寄存器的存储。或者您可以将地址存储在寄存器或指令字中。但是,如果您查看非平凡处理器的指令字实际格式,“寄存器”实际上是特殊的芯片上内存中编号的位置。RISC对它们进行编号的传统使这一点特别明显,但即使在寄存器命名的汇编语言方案中也是如此 - MOV或其他指令将具有几个位来确定指令的类型和格式,并为每个操作数编码寄存器编号。因此,寄存器间接寻址实际上是一个内存位置,它保存另一个内存位置的地址,也就是指针。同样,直接编码在指令字中的数据项的地址也是一个例子,其中一个内存位置(包含指令字的程序存储器)引用另一个实际保存数据的位置。结论:您可以隐藏高级程序员的指针,但只要您的实现基于可寻址的数据存储器/寄存器文件与CPU之间的计算机概念,您无法在实现级别上避免它们。

1

我认为指针可以作为数组的(高效)迭代器非常有用。

例如(C99):

ptrdiff_t stride = 8;
double* data = ...;
size_t size = ...;
const double* end = data + size * stride;

for (double* restrict p = data; p < end; p += stride)
    *p = ...;

你可以看到指针算术在表达意图方面非常有用。能够传递指针和步长来表示子数组也很有用。

一些语言禁止使用指针来操作数据(但允许引用),尽管在这些语言中,我从来没有对它们让你编写作用于数组的函数的方式感到舒适。在C语言中,你可以这样写。

void foo(const double* data, ptrdiff_t stride, size_t size, double* out);

在C#中,你会写成:
void Foo(double[] data, int stride, double[] output);

但现在输出被强制成一个完整的数组,而不是其他东西的子数组,或者在只有一个元素输出的情况下是一个普通的堆栈变量(如果你真的想要,C#提供指针,但让我们假装它没有)。


1

高级语言中是否需要指针?从严格的图灵机意义上来说,不需要。然而,在现实中,我们不是在图灵机上编码——我们使用高级语言编码,开发人员需要某些构造来减轻编写代码的心理负担。指针使得某些抽象(例如链表)更容易表达。因此,虽然在“需要”一词的最严格解释中答案可能是否定的,但在实践中,答案是肯定的,我们确实需要它们。

请阅读StackOverflow FAQ。


1
高级语言倾向于避免使用指针。低级语言也是如此。 - Pubby
不,低级语言并没有避免指针,尽管它们可能避免称之为指针。 - Chris Stratton
@Pubby 这取决于你对“高级语言”的定义。我会把C和C++(以及Pascal)归为“高级语言”--我猜你不会这么认为。 - Onorio Catenacci

0

指针的功能是引用的超集。你可以用引用做的所有事情都可以用指针来完成。指针是比引用更强大的工具,这就是为什么C语言使用指针的原因。它是一种低级强大的语言。

是否有任何情况或特定示例需要使用指针?

是的,例如指针算术运算。

//copy string to a buffer
char buffer[1024];
strcpy(buffer, "hello ");  
strcpy(buffer + 6, "world!");

“需要使用指针才能完成的事情,是否可以不使用它们来实现呢?”
当然可以。如果您想将一个大对象传递给一个方法,而不是复制它,您可以传递一个指向它的指针,但更好的方法是传递一个引用。
void foo(Object const& o); // <- this one is prefered
void foo(Object *o);

这里有一组规则,说明如何将对象传递给function

我们可以将指针作为函数参数发送,但是这可以通过返回的数据来完成吗?

可以做到。返回指针的问题在于“指针指向的存储位置在哪里?”返回本地变量是一个危险的想法。(C++ 11通过移动语义解决了这个问题)

我们可以使用指针来更改函数中的多个变量,但也有解决方法

抱歉,我不理解这个。

我们真的需要指针吗?

是的,我们需要。


0
在编程中,你需要在许多情况下使用指针,特别是当你考虑程序的内存消耗和时间时。例如,当一个大数组要传递给一个不修改它的子程序时,一种单向方法可能更好。然而,将数组传递给函数将要求整个数组被移动到子程序的本地存储区域。这将在时间和空间上都很昂贵。因此,通常通过引用来传递大数组。

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