为什么C大师Dennis Ritchie会在C中引入指针?以及为什么其他编程语言(例如VB.NET或Java或C#)消除了它们?我在Google中发现了一些要点,我也想听听您的评论。人们为什么要消除现代语言中的指针概念?那么为什么他们要用更现代的语言消除指针呢?

您认为指针知识对于新程序员来说仍然重要吗?如今,人们正在使用VB.NET或Java,它们支持的功能比C更高级(并且不使用任何指针概念),而我现在看到的许多人(我的朋友)选择这些语言而忽略了C,因为它们支持高级功能。我告诉他们以C开头。他们说,当您在VB.NET或Java中进行高级的操作(在C中是不可能的)时,学习指针的概念很浪费。

怎么办您认为吗?

更新时间:

我在Google上阅读的评论是:


早期的计算机速度太慢且未优化。
使用指针可以直接访问地址,这样可以节省时间,而不必在函数调用中复制地址。
使用指针的安全性大大降低,这就是Java和C#不包括在内的原因它们。

这些以及我发现的更多内容。我仍然需要一些有价值的答案。这将不胜感激。

评论

Java没有指针?这不是真的。基本上,Java中的每个对象引用都是一个指针。

quant_dev的意思是Java充满了透明使用的指针,而程序员却不能显式使用它们。

这是乔尔·斯波斯基(Joel Spolsky)的相关文章... joelonsoftware.com/articles/fog0000000319.html

“为什么C大师Dennis Ritchie在c语言中引入了指针?”指针未在c中引入,它们直接来自汇编实践,包括名称。

@quaint_dev:好吧,Java确实没有指针。引用不能完成指针可以做的所有事情,因此,尝试以引用的方式理解指针并不是可行的方法(这是很多学习C或C ++的程序员的错误)。指针可以算术。参考不能。 (这种限制在我每次被迫使用Java时都会发臭)

#1 楼

那时,开发人员与金属的距离越来越近。 C本质上是汇编的高级替代品,它几乎与您所能获得的硬件几乎一样,因此很自然地需要指针来有效解决编码问题。但是,指针是锋利的工具,如果使用不当,可能会造成严重损坏。而且,直接使用指针可以解决许多安全问题,而这在当时并不是问题(在1970年,互联网由几所大学中的几十台机器组成,甚至没有这样的名称) ...),但此后变得越来越重要。因此,如今有意识地设计了高级语言以避免原始内存指针。

说“用C语言无法在VB.Net或Java中完成高级的事情”表明了非常有限的观点。至少:-)

首先,所有这些语言(甚至汇编语言)都是图灵完整的,因此,从理论上讲,用一种语言所能做到的一切都是可能的。只需考虑一下一段VB.Net或Java代码的编译和执行会发生什么:最终,它会被翻译成(或映射到)机器代码,因为那是机器唯一能理解的东西。在像C和C ++这样的编译语言中,您实际上可以将等同于原始高级源代码的完整机器代码作为一个或多个可执行文件/库。在基于VM的语言中,获取程序的整个等效机器代码表示形式比较棘手(甚至可能无法实现),但最终仍会存在于运行时系统和JIT的深处。 br />
现在,当然,在特定语言中某些解决方案是否可行是一个完全不同的问题。没有明智的开发人员会开始以汇编形式编写Web应用程序:-)但是请记住,大多数或所有这些高级语言都是基于大量的运行时和类库代码构建的,这非常有用。它是用较低级别的语言(通常是C语言)实现的。 [...]重要吗?


指针背后的概念是间接的。这是一个非常重要的概念,恕我直言,每个优秀的程序员都应在一定程度上掌握它。即使有人只使用高级语言,间接和引用仍然很重要。不理解这一点意味着无法使用一整套非常有效的工具,从长远来看会严重限制一个人解决问题的能力。

所以我的答案是肯定的,如果您想成为一个真正的好人程序员,您还必须了解指针(以及递归-这是新手开发人员的另一个典型绊脚石)。您可能不需要从头开始-我认为C作为当今的第一语言不是最佳的。但是在某个时候,人们应该熟悉间接。没有它,我们将永远无法理解我们正在使用的工具,库和框架是如何工作的。不了解其工具工作原理的工匠是非常有限的。相当公平,人们也可以使用高级编程语言来掌握它。一个很好的石蕊测试正确地实现了一个双向链表-如果您可以用自己喜欢的语言来做,就可以声称您对间接语言的理解足够好。但是,如果没有别的事情,我们应该这样做,以尊重那些设法使用他们曾经拥有的荒谬简单工具(与我们现在拥有的工具相比)来构建令人难以置信的东西的老程序员。我们都站在巨人的肩膀上,承认这一点对我们有好处,而不是假装我们自己就是巨人。

评论


这是一个很好的答案,但并不能真正回答以下问题:“年轻人需要学习指针概念吗?”

–猎鹰
2011年9月5日在9:37

+1好答案。不过,我会删除图灵完整性的参数-对于实际编程,这是一个红色的鲱鱼,稍后您也将注意到。这是可计算性理论,即完成仅意味着在(对于许多语言而言,是无限的)潜在程序空间中存在一个实现相同算法的程序,而不是实际可行或人为可行的算法。只需指出最后所有机器代码就可以证明这一点,而无需植入愚蠢的“我可以用一种语言来做所有事情,因为它们都是一样的,哈哈!”种子。

–user7043
2011-09-5 10:19



+1表示“而且不了解其工具工作原理的工匠非常有限。”

–quickly_now
2011年9月5日上午10:55

同样,不了解指针(和扩展引用)的机制也意味着您不了解浅/深数据结构复制的概念,这可能会导致严重的难以跟踪的错误。即使使用“现代”高级语言。

–马夫里克
2011-09-5 13:11



C被设计为可移植的Unix汇编程序,即接近金属的汇编程序。

–user1249
2011年9月5日于17:04

#2 楼

我认为您需要有所不同。

Java和其他高级语言没有删除指针。他们所做的是删除普通指针算法。

实际上,Java仍然允许使用受保护和受限制的指针算法:数组访问。在普通的旧C语言中,数组访问只不过是取消引用。如果要清楚地传达您在做什么,这是一种不同的表示法,一种语法糖。因此,它也等效于array[index],尽管我认为某些C编译器可能会警告您。
作为推论,*(array+index)等效于index[array]。这仅仅是因为“数组的指针”是数组的第一个条目的地址,而后续元素的地址是通过添加索引来计算的。

在Java中,普通指针算术(引用和取消引用)不再存在。但是,存在指针。他们称它们为引用,但不会改变它的含义。数组访问仍然是一回事:查看地址,添加索引并使用该内存位置。但是,在Java中,它将检查该索引是否在您最初分配的数组的范围内。如果没有,它将抛出异常。

现在Java方法的优点是您没有代码,只是盲目地将任意字节写入任意内存位置。这样可以提高安全性,并提高安全性,因为如果您无法检查缓冲区溢出等问题,则运行时将为您做到这一点。可以在C语言中进行内存安全编程。无法从Java的速度和不安全编程的可能性中受益。

实际上,指针或指针算法并不困难。通常只是以复杂的方式解释它们,而所有指针都是一个大数组(您的内存空间)的索引,所有引用一个值的工作都是为您提供在哪里可以找到它的索引,所有去引用的工作就是查找给定索引的值。 (这只是简化了一下,因为它没有考虑值在内存中的大小取决于其类型的不同。但这只是一个偶然的细节,而不是实际概念的一部分) br />恕我直言,我们工作中的每个人都应该能够理解这一点,否则他们只是处于错误的领域。

评论


+1 Java和C#仍然具有指针,当然还有NullPointerExceptions

– jk。
2011年9月5日下午16:41

还要注意,随着垃圾收集器的移动,引用可能会随着时间指向不同的区域。指针通常是静态的。

–user1249
2011年9月5日于20:54

+1:这个!而且我认为关于指针(一般而言)有两点要牢牢把握:间接寻址(在C,C#,Java等情况下发生)和指针算术(在Java中不会以相同的方式发生)。在我看来,这两个都是重要的概念,对于初学者来说,它们都是主要的绊脚石。但是,它们不应该混淆:如果没有指针算法,间接调用就会发生。

– Joachim Sauer
2011年9月6日下午6:52

实际上,back2dos第一次是正确的,因为(数组+索引)已经考虑了对象的大小(以C表示)。

–马修·弗拉申(Matthew Flaschen)
2011年9月6日15:10

@Cyber​​Skull,答案是在语法上等同于array [index],即*(array + index)。如果要显示编译器如何在内部执行操作,则可以显式地讨论字节或提供程序集。

–马修·弗拉申(Matthew Flaschen)
2011年9月7日15:22

#3 楼

指针的概念在一般的计算机编程知识中很重要。
理解该概念对于任何语言的程序员或程序员都是有益的,即使该语言不直接支持它也是如此。

指针在数据结构(链接列表)和数据库设计(外键)中都有使用。

VB和C#之类的语言可以通过“引用”将数据传递给方法,可以认为

了解内存中的数据分配位置(堆栈还是堆)对于提高算法效率仍然很重要。

学习正确的基础知识很重要我认为。

评论


我发现一般概念会有所帮助,但是我从未发现需要指针的情况(当然,我主要使用Java和PHP)。我的C ++课程针对指针提出的唯一示例是使用它们来创建更复杂的数据结构,例如列表和字典,这些结构以任何高级编程语言开始。

–本·布罗卡(Ben Brocka)
2011年9月5日下午13:05

您在某种程度上是正确的,但是当您将数据传递给方法时,在某些情况下,您很可能会将指针传递给变量。但是,指针的概念是有用的(在我看来),无论其在软件语言中的实现如何。

– NoChance
2011年9月5日下午13:15

@SirTapTap:这是因为,如果您通过某种课程学习了C ++,他们就会教您C ++。不是使用C ++的最佳方法。指针算术通常会被遮盖,因为您可以对C ++有所了解而又不知道。但是,即使迭代通用集合之类的事情也可以通过真实/惯用的C ++中的指针来完成。 (因为这是标准模板库工作方式的基础)

–比利·奥尼尔(Billy ONeal)
2011年9月6日下午0:28

@BillyONeal指针几乎完成了一半的课程,实际上,我仍然没有找到作为程序员的(智能)指针的实际用途,因为我从不需要做任何事情来直接控制内存。当然,总会有课程教学效果不佳的可能性,这并不是我的最爱。

–本·布罗卡(Ben Brocka)
2011年9月6日下午12:53

@SirTapTap:实际使用:STL中的每个集合和算法。 std :: sort,std :: partition,std :: find等。它们与指针一起工作,并且与像指针(迭代器)一样工作的对象一起工作。他们可以处理所有常规收藏;链表,动态数组,双端队列,树或任何其他类型的用户定义的集合。没有指针,您将无法实现这种抽象。

–比利·奥尼尔(Billy ONeal)
2011年9月6日14:42

#4 楼

是的,是的,是的,是的,是的!!!

如果您不了解基本知识,您将永远无法解决您遇到的真正困难,奇怪,困难和复杂的问题。

如果您真的很了解基本知识,那么您在劳动力市场上的市场就会大得多。 10年了,不知道指针如何工作。我(大三)在白板上花了几个小时来教育他。那使我大开眼界。他对很多基本知识没有想法。

尽可能多地了解。

评论


但是基础是什么?汇编,二进制代码?

–西伯利亚人
2011年9月5日下午13:52

尽管您的“尽可能多地了解”的一般观点是合理的,但我会质疑这样一个想法,即您将“永远无法解决您遇到的真正困难,奇怪,困难和复杂的问题”不懂指针。这某种程度上意味着可以使用这些“魔术”指针解决所有困难的问题,事实并非如此。指针之间的概念很有用,但是对于许多编程领域而言,它们并不是直接必需的。

– Dan Diplo
2011年9月5日下午14:10

@Idsa:不,甚至更基本的是,如今许多程序员甚至都不知道晶体管和逻辑门如何在粘性芯片中工作,他们当然应该知道电子如何运动以及量子不确定性对小型化的影响;我什至还没有开始研究庸俗,立顿和野牛!打the野牛粒子!

– Lie Ryan
2011年9月5日15:34



基础知识....诸如如何存储东西之类的东西。字节,单词,有符号和无符号的工作方式之间的区别。指针如何工作。什么字符事物是如何用ASCII编码的(现在是Unicode)。仅使用简单结构如何在内存中创建链接列表。字符串如何真正起作用。从这些小事情中,更大的事情开始发展。

–quickly_now
2011年9月6日下午1:29

尽可能多地了解是一个很好的原则,但是我认为您在马车前面有推车。优秀的开发人员会尽一切努力学习,因为他们是优秀的开发人员。对知识的向往是优秀开发人员的特征。这不是优秀开发人员的原因。尽可能多地去学习并不能使您成为一名优秀的开发人员。它将使您成为步行百科全书,仅此而已。如果您是一名优秀的开发人员,那么您可以运用所获得的知识来解决问题。但是,如果您还不是一个好的开发人员,那么所学的知识将不会给您带来太多好处。

– corsiKa
2011年9月6日18:01

#5 楼

是的,理解很重要。

几个月前,我正在用C#编程,我想复制一个列表。当然我所做的是NewList = OldList;,然后开始修改NewList。当我尝试打印两个列表时,它们都是相同的,因为NewList只是指向OldList的指针,而不是副本,因此实际上我一直在更改OldList。我花了很长时间才弄清楚一个人,但是我的一些同学并没有那么快,必须解释为什么会这样。

示例:

List<int> a = new List<int>();
a.Add(2);
a.Add(9);
a.Add(8);
a.Add(1);
List<int> b = new List<int>();
b = a; //Does not make a copy, b is just a synonym!
b.Sort();
for (int i = 0; i < a.Count; i++)
{
    Console.WriteLine("a: " + a[i] + " b: " + b[i]);
}


结果当然是这样的:

a: 1 b: 1
a: 2 b: 2
a: 8 b: 8
a: 9 b: 9


知道如何使用它们并不重要了解他们至关重要!

评论


相反,最重要的是为什么要使用它们以及何时使用它们:)

–niko
2011年9月5日在12:29

“ NewList只是指向OldList的指针”-确切地说,NewList和OldList都只是指向同一List对象的指针。

–彼得·托克(PéterTörök)
2011年12月3日在21:19



了解您为b创建的新列表不再具有对它的引用,现在已经成为垃圾,这也很重要。

– TMN
2012年7月26日15:23

#6 楼

指向概念!=指向算术!=指向语法

首先重要的是,如果您需要(并且确实需要)理解深层/浅层复制,按引用传递/按值传递等。只有当您的语言允许您使用它们时,其他两个事项才重要。

评论


如今,您只需要了解引用的基本概念,而无需了解指针语法/数学。那天我在C中学习了指针(带有算术和语法)。我现在使用的语言不会处理允许您执行不安全操作的C样式指针。可以理解为什么在python中a = [1,2]; b = a; a.append(3),a和b都将引用相同的对象[1,2,3],却不知道C语言那样的东西,数组的ith元素可以由arr [i]或i [arr引用],因为它们都是*(arr + i)。我更喜欢不使用i [arr]的语言。

– jimbob博士
2011年9月6日下午3:31

“只有当您的语言允许您使用它们时,其他两个才有意义。” -该句子带有自己的自毁对象。顾名思义,按您的语言是极不可能与明天使用的语言相同。明天您可能会遇到启用指针的语言。底线?更好的人现在就可以一劳永逸地掌握它。这并不难,但是值得。

– JensG
14-10-17在0:55



#7 楼


为什么C大师Dennis Ritchie会在C语言中引入指针?


因为指针是一种非常强大的机制,可以用多种方式使用。


为什么用VB.NET或Java或C#之类的其他编程语言来消除它们呢?


因为指针是一种非常危险的机制,可以在许多方面滥用。

我认为程序员应该学习指针,但是从教育的角度来看,尽早引入它们是不明智的。原因是它们被用于许多不同的目的,作为初学者很难说出为什么您在特定情况下使用指针。


动态分配(new T
递归数据结构(struct T { T* next; /* ... */ };
数组迭代器(for (T* p = &a[0]; p != &a[0] + n; ++p) { ... }) />子类型多态性(T* new_pointer = existing_pointer;
通过引用进行旧式调用(T* pointer_to_base = pointer_to_derived;
可选类型(mutate(&object);
经验丰富的程序员的优雅和优雅,以及编程新手的巨大困惑潜力。

评论


“为什么C大师Dennis Ritchie会在C语言中引入指针?因为指针是一种非常强大的机制,可以通过多种方式使用。” -我不知道一个事实,但是我想这与将机器指令包装到C语言中以及C的前身有关。汇编程序程序员习惯于在指针中进行思考,因此本来可以如果他没有使用这些众所周知的强大机制,那将是一个惊喜。对于1978年甚至1960年代,任何其他事情都不会太遥远。

– JensG
2014年10月17日在1:06

#8 楼

为什么?您可以使用Forms Designer和代码生成器编写一个庞大的系统。这还不够吗? (讽刺)

现在,认真的说来,指针在许多领域并不是编程的关键部分,但是它们使人们能够了解内部结构的工作方式。而且,如果没有人了解内部结构是如何工作的,那么就有可能将SQL2020,Windows 15和Linux 20.04编写为运行30层抽象层的垃圾收集虚拟机,并使用JavaScript通过IDE生成代码。

这绝对不是我想要看到的。

所以是的,他们确实必须这样做!

评论


良好的幽默感! +1并完全同意。

– heltonbiker
2011年9月5日于13:04

#9 楼

Java和C#都没有消除指针,它们具有几乎相同的引用。消除的是指针算法,可以在入门课程中省略。他们)。

在C ++和Java中考虑以下内容,我想在C#中并没有太大区别:aClass *x = new aClass(); aClass x = new aClass();
指针和引用之间并没有太大的区别,对吧?除非有必要,并且在使用高级模型进行编程时,否则应避免算术运算,因此那里没有太多问题。

#10 楼

专业的程序员应该掌握指针。

想要了解编程的人应该了解它的存在和含义,但不一定要使用它们。

想要解决的人通过编程产生的个人问题(像我一样,使用很多Python脚本)完全可以忽略它们。

,那是我的意见...; o)

#11 楼

可变地址指针是更广义的间接概念的特定情况。在大多数(所有?)现代语言中,都在许多结构(例如委托和回调)中使用了间接寻址。了解间接的概念使您知道何时以及如何最佳地使用这些工具。

#12 楼

绝对是的!编程的每个人都需要了解指针和间接性。

指针是如何以所有语言完成大量数据访问。指针是所有微处理器的硬件功能。诸如Java,VB和C#之类的高级语言从本质上限制了使用语言的用户对带有引用的指针的直接访问。引用通过语言的内存管理方案来引用对象(例如,可以是带有元数据的指针或仅是内存表的数字)。

了解指针的工作方式是理解计算机实际工作方式的基础工作。指针也比引用更灵活和强大。例如,数组从索引零开始的原因是,数组实际上是指针算术的简写形式。在不了解指针如何工作的情况下,许多新手程序员无法完全获得数组。

int a, foo[10];
foo[2] = a;


指针算术的第二行是:
*(foo + sizeof(int) * 2) = a;


如果不了解指针,就无法理解内存管理,堆栈,堆甚至数组!此外,还需要了解指针,并取消引用以了解如何传递函数和对象。

TL:DR:了解指针是理解计算机实际工作的基础。

#13 楼

我认为可以归结为这样一个事实,即由于程序员对运行的直接硬件的处理较少,因此处理指针的需求逐渐减少。例如,以完全适合专用硬件具有的640字节内存模块序列的方式分配链表数据结构。

手动处理指针可能容易出错(导致内存不足)漏洞和可利用的代码),并且花费很长时间才能正确处理。因此,Java和C#等现在都通过它们的虚拟机(VM)为您管理内存和指针。尽管VM一直在不断改进,但是这可以说效率不如使用原始C / C ++。

C(和C ++)仍然是广泛使用的语言,尤其是在高性能计算,游戏和嵌入式硬件领域。我个人很感激我了解了指针,因为到Java引用的转换(类似于指针的概念)非常容易,当我看到我的第一个NullPointerException时我并没有迷路(它实际上应该称为NullReferenceException,但我离题了) 。

我建议您学习有关指针的概念,因为它们仍然支撑着许多数据结构等。然后继续选择您喜欢使用的语言,并知道如果有NPE之类的东西出现,您知道真正发生了什么。

#14 楼

这是客观事实:

有些语言支持直接内存访问(指针),有些则不支持。每种情况都有充分的理由。


就像在这里所说的那样,在C时代,自动内存管理并不像今天这样复杂。无论如何,人们已经习惯了。那时,优秀的程序员比我们这一代(我21岁)对计算机程序有更深入的了解。他们在大型机上一直使用打孔卡和等待几天的编译时间。他们可能知道为什么代码中的每一点都存在。
C之类的语言的明显优点是,它们使您可以更好地控制程序。这些天,您何时真正需要它?仅在创建基础结构应用程序(例如与OS相关的程序和运行时环境)时。
如果您只想开发良好,快速,健壮和可靠的软件,那么自动内存管理通常是您的更好选择。 br事实是,在软件开发历史过程中,直接内存访问已被滥用。人们以前创建的程序会泄漏内存,实际上由于冗余的内存分配而速度较慢(在C语言中,为每个分配分配扩展进程的虚拟内存空间很容易并且很普遍)。在分配和释放内存方面,比99%的程序员做得更好。最重要的是,它们使您在想要的程序流中具有更大的灵活性,因为(通常)您没有在适当的时间和地点释放分配的内存。
关于知识。我认为程序员知道如何实现编程环境是令人钦佩的。不一定是最小的细节,而是全局。

我认为了解指针的工作原理(至少)很有趣。与知道如何实现多态性相同。您的过程从何处获得记忆,以及如何获得记忆。
这些都是我个人一直很感兴趣的事情。老实说,他们使我成为了一名更好的程序员,但对于任何想成为一名优秀程序员的人来说,它们都不是教育上的必需品。无论哪种情况,了解更多信息通常会使您的工作更好。


我的看法,如果您需要做的只是用Java创建应用程序或C#之类的东西,那么您需要专注于适当的设计和实现技术。可测试的代码,简洁的代码,灵活的代码。按此顺序。

因为即使您不了解所有的细微细节,做某事的人也可以将您创建的内容更改为性能更好的东西。一旦有了适当,干净和可测试的设计(通常是大多数工作),这通常就不是一件容易的事。

如果我是一名面试官,希望聘请一个高薪的人级别的语言应用程序,这将是我最感兴趣的事情。

底层的知识是一种奖励。这对于调试和偶尔创建稍微更好的解决方案很有用。专业地使您成为一个有趣的人。它使您在工作场所受到尊重。

但是在当今世界,这不是神圣的要求。

#15 楼

对于高级OO语言中的大多数实践目的而言,了解引用就足够了,您实际上并不需要了解这些语言如何如何根据指针来实现引用。

还有很多功能和现代的多范式方法,我认为它比能够执行花哨的指针算法要有价值得多,写第1000个优化的字符串复制函数的性能可能比String差。

我建议您先学习更多不同的高级概念,然后再尝试学习不同设计的语言以拓宽您的视野,然后再尝试专门研究

我经常看到在缓存(内存优化),SQL优化或仅进行Web服务器配置调整时,微优化Web servlet或类似代码以获得5%的收益的尝试完全失败。可以轻松完成100%或更高的产量。在大多数情况下,摆弄指针是过早的优化。

#16 楼

当然,如果您真的想成为一名优秀的程序员,我们需要有一个彻底的指针概念。指针概念的原因是可以直接获取您的价值,并且在时间限制下变得更加高效和有效。

现在,考虑到移动应用程序(其内存非常有限),我们现在需要请非常小心地使用它,以便其操作能很快获得用户的响应。为此,我们需要直接参考其价值...

考虑Apple的设备或Objective C语言,完全只使用指针概念。在目标C中声明的所有变量都具有Pointer。您需要浏览Objective C的Wiki

评论


如今的移动应用程序具有比C设想的某些数据中心更多的可用内存。许多移动应用程序都是用Java或完全html + javascript编写的,所有这些都没有指针(确实具有引用)。非常专业的程序员中只有很少一部分能看到底层的OS层。

–Jürgen Strobel
2011年9月28日在22:04