Müssen die jungen Köpfe die Zeigerkonzepte lernen?


89

Warum hat der C-Meister Dennis Ritchie Zeiger in C eingeführt? Und warum haben die anderen Programmiersprachen wie VB.NET oder Java oder C # sie beseitigt? Ich habe einige Punkte in Google gefunden und möchte auch Ihre Kommentare anhören. Warum eliminieren sie Zeigerkonzepte in modernen Sprachen?

Die Leute sagen, C ist die Basissprache und Zeiger sind das Konzept, das C mächtig und herausragend macht und C immer noch dazu bringt, mit moderneren Sprachen zu konkurrieren. Warum haben sie dann Zeiger in moderneren Sprachen entfernt?

Denken Sie, dass das Wissen über Zeiger für neue Programmierer immer noch wichtig ist? Heutzutage verwenden die Leute VB.NET oder Java, das fortgeschrittenere Funktionen als C unterstützt (und keine Zeigerkonzepte verwendet), und viele Leute, wie ich jetzt sehe (meine Freunde), wählen diese Sprachen aus und ignorieren C, da sie fortgeschrittene Funktionen unterstützen. Ich sage ihnen, sie sollen mit C beginnen. Es ist eine Verschwendung, die Konzepte von Zeigern zu erlernen, wenn Sie die fortgeschrittenen Dinge in VB.NET oder Java ausführen, die in C nicht möglich sind.

Was denkst du?

Aktualisiert :

Die Kommentare, die ich bei Google gelesen habe, sind:

  1. Die früheren Computer waren zu langsam und nicht optimiert.

  2. Durch die Verwendung von Zeigern kann direkt auf eine Adresse zugegriffen werden. Dies spart Zeit, anstatt bei Funktionsaufrufen eine Kopie davon zu erstellen.

  3. Die Sicherheit bei der Verwendung von Zeigern ist erheblich schlechter, weshalb sie in Java und C # nicht enthalten sind.

Dies und noch einiges mehr, was ich gefunden habe. Ich brauche noch einige wertvolle Antworten. Das wäre sehr dankbar.


52
Java hat keine Zeiger? Das ist nicht wahr. Jede Objektreferenz in Java ist im Grunde genommen ein Zeiger.
quant_dev

20
Was quant_dev bedeutet, ist, dass Java voll von Zeigern ist, die transparent verwendet werden, während Programmierer sie nicht explizit verwenden können.
Sakisk

9
Hier ist ein Artikel von Joel Spolsky, der relevant ist ... joelonsoftware.com/articles/fog0000000319.html
Joe Internet

11
"Warum hat der C-Meister Dennis Ritchie Zeiger in c eingeführt?" Zeiger wurden in c nicht eingeführt, sie kamen direkt aus der Montagepraxis, einschließlich des Namens.
dmckee

14
@quaint_dev: Nun, Java hat wirklich keine Zeiger. Referenzen können nicht alles, was Zeiger können. Der Versuch, Zeiger in Bezug auf Referenzen zu verstehen, ist also nicht der richtige Weg (und ein Fehler, den viele Programmierer beim Erlernen von C oder C ++ machen). Zeiger können rechnen. Referenzen können nicht. (Eine Einschränkung, die jedes Mal wirklich stinkt, wenn ich gezwungen bin, Java zu verwenden)
Billy ONeal

Antworten:


128

Damals arbeiteten die Entwickler viel näher am Metall. C war im Wesentlichen ein Ersatz für Baugruppen auf höherer Ebene, der fast so nah an der Hardware ist, wie Sie es bekommen können. Daher war es selbstverständlich, dass Sie Zeiger benötigten, um Codierungsprobleme effizient zu lösen. Zeiger sind jedoch scharfe Werkzeuge, die bei unsachgemäßer Verwendung große Schäden verursachen können. Die direkte Verwendung von Zeigern eröffnet auch die Möglichkeit vieler Sicherheitsprobleme, die damals kein Thema waren (1970 bestand das Internet aus ein paar Dutzend Computern an mehreren Universitäten, und es wurde nicht einmal so genannt) ...), wurde aber seitdem immer wichtiger. Heutzutage sind höhere Sprachen bewusst so konzipiert, dass sie keine rohen Speicherzeiger mehr enthalten.

Zu sagen, dass "fortgeschrittene Dinge, die in VB.Net oder Java gemacht werden, in C nicht möglich sind", zeigt, gelinde gesagt, einen sehr begrenzten Standpunkt :-)

Erstens sind alle diese Sprachen (auch die Assemblierung) vollständig, so dass theoretisch alles, was in einer Sprache möglich ist, in allen möglich ist. Denken Sie nur daran, was passiert, wenn ein Teil des VB.Net- oder Java-Codes kompiliert und ausgeführt wird: Schließlich wird er in Maschinencode übersetzt (oder diesem zugeordnet), da dies das einzige ist, was die Maschine versteht. In kompilierten Sprachen wie C und C ++ können Sie den gesamten Maschinencode, der dem ursprünglichen Quellcode der höheren Ebene entspricht, als eine oder mehrere ausführbare Dateien / Bibliotheken abrufen. In VM-basierten Sprachen ist es schwieriger (und möglicherweise sogar nicht möglich), die gesamte entsprechende Maschinencodedarstellung Ihres Programms abzurufen, aber irgendwann befindet sich das Programm irgendwo in den tiefen Nischen des Laufzeitsystems und der JIT.

Nun ist es natürlich eine ganz andere Frage, ob eine Lösung in einer bestimmten Sprache möglich ist. Kein vernünftiger Entwickler würde anfangen, eine Web-App in Assembler zu schreiben :-) Aber es ist nützlich zu bedenken, dass die meisten oder alle dieser höheren Sprachen auf einer riesigen Menge Laufzeit- und Klassenbibliothekscode aufbauen, einem großen Teil davon die in einer niedrigeren Sprache implementiert ist, typischerweise in C.

Um also auf die Frage zu kommen,

Halten Sie Kenntnisse über Hinweise auf die Jugendlichen [...] für wichtig?

Das Konzept hinter Zeigern ist Indirektion . Dies ist ein sehr wichtiges Konzept und meiner Meinung nach sollte jeder gute Programmierer es auf einer bestimmten Ebene verstehen. Auch wenn jemand nur mit höheren Sprachen arbeitet, sind Indirektion und Referenzen immer noch wichtig. Wenn man dies nicht versteht, kann man nicht eine ganze Klasse von sehr wirksamen Werkzeugen verwenden, was auf lange Sicht die Fähigkeit zur Problemlösung ernsthaft einschränkt.

Meine Antwort lautet also: Ja, wenn Sie ein wirklich guter Programmierer werden möchten, müssen Sie auch Zeiger verstehen (und auch Rekursion - dies ist der andere typische Stolperstein für angehende Entwickler). Sie brauchen vielleicht nicht damit zu beginnen - ich denke nicht, dass C heutzutage als Muttersprache optimal ist. Aber irgendwann sollte man sich mit Indirektion vertraut machen. Ohne sie können wir nie verstehen, wie die von uns verwendeten Tools, Bibliotheken und Frameworks tatsächlich funktionieren. Und ein Handwerker, der nicht versteht, wie seine Werkzeuge arbeiten, ist sehr begrenzt. Fairerweise kann man es auch in höheren Programmiersprachen verstehen. Ein guter Lackmustest besteht darin, eine doppelt verknüpfte Liste korrekt zu implementieren. Wenn Sie dies in Ihrer bevorzugten Sprache tun können, können Sie behaupten, dass Sie die Indirektion gut genug verstehen.

Aber wenn nicht für irgendetwas anderes, sollten wir es tun, um Respekt für die Programmierer der alten Zeit zu erlernen, die es geschafft haben, unglaubliche Dinge mit den lächerlich einfachen Werkzeugen zu bauen, die sie hatten (im Vergleich zu dem, was wir jetzt haben). Wir alle stehen auf den Schultern der Riesen, und es tut uns gut, dies anzuerkennen, anstatt so zu tun, als wären wir selbst die Riesen.


5
Dies ist eine gute Antwort, aber sie beantwortet nicht wirklich die Frage: "Müssen die jungen Köpfe die Zeigerkonzepte lernen?"
Falcon

11
+1 Gute Antwort. Ich würde das Argument der Vollständigkeit jedoch fallen lassen - für die praktische Programmierung ist es ein roter Hering, wie auch Sie später bemerken. Es ist eine Berechnungstheorie, dh Vollständigkeit bedeutet nur, dass es ein Programm im (für viele Sprachen unendlichen) Raum potenzieller Programme gibt, das den gleichen Algorithmus implementiert, nicht ob es tatsächlich machbar oder sogar menschlich möglich ist. Nur darauf hinzuweisen, dass alles Maschinencode am Ende ist, beweist, dass es genauso gut ist, ohne das blöde "Ich kann alles in einer Sprache tun, da sie alle gleich sind, harhar!" Samen.

5
+1 für "Und ein Handwerker, der nicht versteht, wie seine / ihre Werkzeuge arbeiten, ist sehr begrenzt."
schnell_now

6
Wenn Sie die Mechanismen von Zeigern (und durch Verweise auf Erweiterungen) nicht verstehen, verstehen Sie folglich nicht die Konzepte einer flachen / tiefen Datenstrukturkopie, die schwerwiegende, schwer zu verfolgende Fehler verursachen kann. Auch in "modernen" Hochsprachen.
Mavrik

1
C wurde entwickelt portable Assembler für Unix sein, dh in der Nähe des Metalls.

39

Ich denke, Sie müssen sich unterscheiden.

Java und andere übergeordnete Sprachen haben keine Zeiger entfernt. Was sie taten, war, einfache Zeigerarithmetik zu entfernen.

Tatsächlich erlaubt Java immer noch eine geschützte und eingeschränkte Zeigerarithmetik: den Array-Zugriff. In C ist der Array-Zugriff nichts anderes als eine Dereferenzierung. Es ist eine andere Schreibweise, ein syntaktischer Zucker, um klar zu kommunizieren, was Sie tun.
Trotzdem array[index]ist gleichbedeutend mit *(array+index). Aus diesem Grund ist es auch äquivalent zu, index[array]obwohl ich vermute, dass einige C-Compiler Ihnen eine Warnung geben könnten, wenn Sie das tun.
Als Konsequenz pointer[0]ist äquivalent zu *pointer. Das liegt einfach daran, dass der "Zeiger auf ein Array" die Adresse des ersten Eintrags des Arrays ist und die Adressen der nachfolgenden Elemente durch Hinzufügen des Index berechnet werden.

In Java gibt es keine einfachen Zeigerarithmetiken (Referenzieren und Dereferenzieren) mehr. Es gibt jedoch Hinweise. Sie nennen sie Referenzen, aber es ändert nichts daran, was es ist. Und der Array-Zugriff ist immer noch genau dasselbe: Schauen Sie sich die Adresse an, fügen Sie den Index hinzu und verwenden Sie diesen Speicherort. In Java wird jedoch geprüft, ob dieser Index innerhalb der Grenzen des Arrays liegt, das Sie ursprünglich zugewiesen haben. Wenn nicht, wird eine Ausnahme ausgelöst.

Der Vorteil des Java-Ansatzes besteht nun darin, dass Sie keinen Code haben, der einfach beliebige Bytes blind in beliebige Speicherstellen schreibt. Dies erhöht die Sicherheit, da die Laufzeitumgebung dies für Sie erledigt, wenn Sie den Pufferüberlauf nicht überprüfen.

Der Nachteil dabei ist, dass es einfach weniger mächtig ist. In C ist eine speichersichere Programmierung möglich. In Java kann man nicht von der Geschwindigkeit und den Möglichkeiten einer unsicheren Programmierung profitieren.

An Zeigern oder Zeigerarithmetik ist eigentlich nichts Schwieriges. Sie werden normalerweise auf verschlungene Weise erklärt, während ein Zeiger lediglich ein Index für ein riesiges Array (Ihren Speicherplatz) ist. Wenn Sie auf einen Wert verweisen, erhalten Sie lediglich den Index, in dem Sie ihn finden der Wert bei einem gegebenen Index. (Dies ist nur ein bisschen vereinfacht, da nicht berücksichtigt wird, dass die Werte im Speicher je nach Typ unterschiedlich groß sind. Dies ist jedoch eher ein umständliches Detail als ein Teil des eigentlichen Konzepts.)

IMHO, jeder in unserer Arbeit sollte das verstehen können, oder sie sind einfach im falschen Bereich.


13
+1 Java und C # haben noch Zeiger und natürlich NullPointerExceptions
jk.

5
Beachten Sie auch, dass Verweise im Laufe der Zeit möglicherweise auf andere Bereiche verweisen, da der Garbage Collector die Daten verschiebt. Zeiger sind normalerweise statisch.

3
+1: das! Und ich denke , es gibt zwei harte Dinge über Zeiger (im Allgemeinen) zu erfassen: indirection (die in C geschieht, C #, Java, ...) und Zeigerarithmetik (die nicht in Java in der gleichen Art und Weise geschehen). Meiner Meinung nach beide sind wichtige Konzepte zu lernen , und beide sind große Stolpersteine für Anfänger. Sie sollten jedoch nicht verwechselt werden: Indirektion kann ohne Zeigerarithmetik erfolgen.
Joachim Sauer

2
Eigentlich back2doswar das erste mal richtig, da (array + index)schon die Größe der Objekte berücksichtigt wird (in C).
Matthew Flaschen

4
@ CyberSkull, die Antwort gab das syntaktische Äquivalent von array[index], und das ist *(array+index). Wenn Sie zeigen möchten, wie der Compiler intern vorgeht, können Sie explizit über Bytes sprechen oder die Assembly angeben.
Matthew Flaschen

24

Das Konzept der Zeiger ist im allgemeinen Wissensbestand der Computerprogrammierung wichtig. Das Verständnis des Konzepts ist gut für angehende Programmierer oder Programmierer jeder Sprache, auch wenn die Sprache es nicht direkt unterstützt.

Zeiger werden in Datenstrukturen (verknüpfte Listen) und im Datenbankdesign (Fremdschlüssel) verwendet.

Sprachen wie VB und C # können Daten als "Referenz" an Methoden übergeben, die als Zeigertyp betrachtet werden können.

Für die Effizienz von Algorithmen ist es weiterhin wichtig zu verstehen, wo Daten im Speicher zugeordnet werden (Stack vs. Heap).

Das richtige Erlernen der Grundlagen ist meiner Meinung nach wichtig.


Ich finde das allgemeine Konzept hilfreich, aber ich habe nie eine Situation gefunden, in der ich einen Zeiger benötige (vorausgesetzt, ich verwende hauptsächlich Java und PHP). Die einzigen Beispiele, die meine C ++ - Kurse jemals für Zeiger ausgearbeitet haben, waren die Erstellung komplexerer Datenstrukturen wie Listen und Wörterbücher, die in jeder höheren Programmiersprache existieren.
Ben Brocka,

2
In gewisser Hinsicht sind Sie korrekt, aber wenn Sie Daten an Methoden übergeben, besteht die Möglichkeit, dass Sie in einigen Fällen einen Zeiger auf die Variable übergeben. Das Konzept eines Zeigers ist jedoch (meiner Meinung nach) nützlich, unabhängig von seiner Implementierung in einer Softwaresprache.
NoChance

1
@ SirTapTap: Das liegt daran, dass wenn Sie C ++ in einer Art Kurs gelernt haben, diese Ihnen C ++ beibringen. Nicht der beste Weg, um C ++ zu verwenden. Die Zeigerarithmetik wird in der Regel vertuscht, da Sie über Kenntnisse in C ++ verfügen und diese nicht kennen. Aber auch Dinge wie das Durchlaufen einer allgemeinen Sammlung werden mit Zeigern in realem / idiomatischem C ++ durchgeführt. (Da dies die Grundlage für die Funktionsweise der Standardvorlagenbibliothek ist)
Billy ONeal

@BillyONeal Zeiger waren fast die Hälfte des Kurses, wirklich, ich habe als Programmierer noch nie eine praktische Verwendung für (kluge) Zeiger gefunden, vorausgesetzt, ich brauchte nie die direkte Kontrolle über das Gedächtnis in irgendetwas, was ich getan habe. Natürlich gibt es immer die Möglichkeit, dass der Kurs schlecht unterrichtet wurde, es war nicht gerade mein Favorit.
Ben Brocka

1
@SirTapTap: Praktische Anwendung: Jede Sammlung und jeder Algorithmus in der STL. std::sort, std::partition, std::findUsw. Sie arbeiten mit Zeigern, und sie arbeiten mit Objekten , die wie Zeiger (Iteratoren) handeln. Und sie bearbeiten jede allgemeine Sammlung. verknüpfte Listen, dynamische Arrays, deques, Bäume oder jede andere Art von benutzerdefinierter Sammlung. Eine solche Abstraktion ist ohne Zeiger nicht möglich.
Billy ONeal

19

Ja, ja, ja, ja und ja !!!

Wenn Sie die Grundlagen nicht kennen, werden Sie NIEMALS in der Lage sein, die wirklich schwierigen, seltsamen, schwierigen und komplizierten Probleme zu lösen, die Ihnen in den Weg kommen.

Und wenn Sie die Grundlagen wirklich gut verstehen, sind Sie auf dem Arbeitsmarkt VIEL besser vermarktbar.


Ich habe einmal mit einem Typen gearbeitet, der seit 10 Jahren programmiert und keine Ahnung hatte, wie Zeiger funktionieren. Ich (viel jünger) verbrachte Stunden an einem Whiteboard, um ihn zu unterrichten. Das hat mir die Augen geöffnet. Er hatte keine Ahnung von so vielen grundlegenden Dingen.

Wissen Sie so viel wie möglich.


Aber was sind die Grundlagen? Assembler, Binärcode?
SiberianGuy

5
Während Ihr allgemeiner Standpunkt "so viel wie möglich zu wissen" ein vernünftiger ist, würde ich die Idee in Frage stellen, dass Sie "NIEMALS in der Lage sein werden, die wirklich harten, seltsamen, schwierigen und komplizierten Probleme zu lösen, die Ihnen in den Weg kommen", wenn Sie Verstehe keine Zeiger. Dies impliziert irgendwie, dass alle schwierigen Probleme mit diesen "magischen" Zeigern gelöst werden können, was nicht der Fall ist. Die Konzepte zwischen Zeigern sind nützlich zu wissen, aber für viele Bereiche der Programmierung nicht direkt wesentlich.
Dan Diplo

4
@Idsa: Nein, noch grundlegender: Viele Programmierer wissen heutzutage nicht einmal, wie Transistoren und Logikgatter in den alten Chips funktionieren, und sie hätten sicherlich wissen müssen, wie sich Elektronen bewegen und wie sich Quantenunsicherheit auf die Miniaturisierung auswirkt. Ich habe noch nicht einmal mit Quacksalbern, Liptons und Bisons angefangen! und die Hiccups Bisonpartikel!
Lie Ryan

2
Grundlagen ... Dinge wie das Speichern von Dingen. Der Unterschied zwischen einem Byte, einem Wort und der Arbeitsweise ohne Vorzeichen. Wie Zeiger funktionieren. Was für ein Charakter ist. Wie Dinge in ASCII codiert sind (und heutzutage in Unicode). Wie eine verknüpfte Liste nur mit einfachen Strukturen im Speicher erstellt werden kann. Wie Saiten WIRKLICH funktionieren. Aus diesen kleinen Dingen wachsen größere Dinge.
quick_now

5
Es ist ein gutes Prinzip, so viel wie möglich zu wissen, aber ich denke, Sie haben den Karren vor dem Pferd. Gute Entwickler bemühen sich zu lernen, was sie können, weil sie gute Entwickler sind. Die Sehnsucht nach Wissen ist ein Merkmal eines guten Entwicklers. Es ist nicht die Ursache eines guten Entwicklers. Wenn Sie so viel wie möglich lernen, werden Sie kein guter Entwickler. Es wird Sie zu einer wandelnden Enzyklopädie machen, sonst nichts. Wenn Sie ein guter Entwickler sind, können Sie dann das erlangte Wissen anwenden, um Probleme zu lösen. Aber wenn Sie nicht bereits ein guter Entwickler waren, bringt Ihnen das Wissen nicht viel.
corsiKa

18

Ja, Verständnis ist wichtig.

Vor ein paar Monaten programmierte ich in C # und wollte eine Liste kopieren. Natürlich habe ich NewList = OldList;angefangen zu modifizieren NewList. Als ich versuchte, beide Listen auszudrucken, waren sie beide gleich, da NewListes sich nur um einen Zeiger OldListund nicht um eine Kopie handelte, also änderte ich mich die OldListganze Zeit. Es dauerte nicht lange, bis ich das herausgefunden hatte, aber einige meiner Klassenkameraden waren nicht so schnell und mussten erklärt werden, warum dies geschieht.

Beispiel:

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]);
}

Und das Ergebnis sieht natürlich so aus:

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

Zu wissen, wie man sie benutzt, ist nicht so wichtig, aber es ist entscheidend, sie zu verstehen!


2
Stattdessen, warum man sie benutzt und wann man sie benutzt, ist das Wichtigste :)
niko

5
NewListWar nur ein Zeiger auf OldList - um genau zu sein, die beide NewListund OldListwaren nur Zeiger, auf das gleiche Bezug ListObjekt.
Péter Török

Es ist auch wichtig zu verstehen, dass die neue Liste, für die Sie erstellt bhaben, keine Referenzen mehr enthält und jetzt Müll ist.
TMN

14

Zeig das Konzept! = Zeig die Arithmetik! = Zeig die Syntax

Das erste ist immer wichtig, wenn Sie Verständnis für tiefe / flache Kopien benötigen (und dies auch tun), Referenz- / Wertübergabe usw. Die anderen beiden sind nur wichtig, wenn Sie sie in Ihrer Sprache verwenden können.


1
Heutzutage müssen Sie nur das Grundkonzept der Referenzen kennen, nicht die Zeigersyntax / Mathematik. Ich habe früher Zeiger (mit Arithmetik und Syntax) in C gelernt. Die Sprachen, in denen ich jetzt programmiere, behandeln keine C-Zeiger, mit denen Sie unsichere Dinge tun können. Man kann verstehen, warum in Python a=[1,2]; b=a; a.append(3)beide aund bbeide auf dasselbe Objekt verweisen, [1,2,3]ohne etwas wie in C zu wissen, auf das das ith-Element eines Arrays durch arr[i]oder i[arr]wie beide verwiesen werden kann *(arr+i). Ich bevorzuge, wenn die Sprache nicht verwendet werden i[arr]darf.
Dr. Jimbob

" Die anderen beiden sind nur wichtig, wenn Sie sie in Ihrer Sprache verwenden können. " - Dieser Satz trägt seinen eigenen Selbstzerstörer in sich. Es ist per Definition sehr unwahrscheinlich, dass die Sprache du jour dieselbe ist, die morgen verwendet wird. Und morgen werden Sie möglicherweise mit einer Zeigersprache konfrontiert. Endeffekt? Besser man fasst es jetzt, einmal und für immer. Es ist nicht so schwer, aber es lohnt sich.
JensG

14

Warum hat der C-Meister Dennis Ritchie Zeiger in C eingeführt?

Weil Zeiger ein sehr leistungsfähiger Mechanismus sind, der auf viele Arten verwendet werden kann.

Und warum haben die anderen Programmiersprachen wie VB.NET oder Java oder C # sie beseitigt?

Weil Zeiger ein sehr gefährlicher Mechanismus sind, der auf viele Arten missbraucht werden kann.

Ich denke, Programmierer sollten etwas über Zeiger lernen, aber aus pädagogischer Sicht ist es nicht ratsam, sie frühzeitig einzuführen. Der Grund dafür ist, dass sie für so viele verschiedene Zwecke verwendet werden, dass es für Anfänger schwer zu sagen ist, warum Sie unter bestimmten Umständen einen Zeiger verwenden.

Hier ist eine unvollständige Liste, wofür Zeiger verwendet werden:

  • dynamische Zuordnung ( new T)
  • rekursive Datenstrukturen ( struct T { T* next; /* ... */ };)
  • Iteratoren über Arrays ( for (T* p = &a[0]; p != &a[0] + n; ++p) { ... })
  • gemeinsamer Zugriff auf Objekte ( T* new_pointer = existing_pointer;)
  • Subtyp Polymorphismus ( T* pointer_to_base = pointer_to_derived;)
  • Legacy-Aufruf nach Referenz ( mutate(&object);)
  • Optionale Typen ( if (p) { /* ... */ })

Beachten Sie, dass die Verwendung eines einzigen Mechanismus für alle diese Konzepte sowohl die Kraft als auch die Eleganz für den erfahrenen Programmierer und das große Verwirrungspotential für jemanden demonstriert, der neu in der Programmierung ist.


" Warum hat der C-Meister Dennis Ritchie Zeiger in C eingeführt ? Weil Zeiger ein sehr leistungsfähiger Mechanismus sind, der auf viele Arten verwendet werden kann." - Ich weiß es nicht genau, aber ich vermute, es hat etwas mit Maschinenanweisungen zu tun, die in die C-Sprache eingebunden werden, und die Vorgänger von C. Assembler-Programmierern sind es gewohnt, in Zeigern zu denken Eine Überraschung, wenn er diese bekannten leistungsstarken Mechanismen nicht benutzt hätte. Alles andere wäre 1978 oder sogar in den 1960er Jahren zu weit weg gewesen.
JensG

12

Warum? Sie können ein riesiges System mit Formulardesigner und Codegenerator schreiben. Reicht es nicht (Ironie)

Und jetzt im Ernst, Zeiger sind in vielen Bereichen kein entscheidender Bestandteil der Programmierung, aber sie ermöglichen es den Menschen zu verstehen, wie die Interna funktionieren. Und wenn wir niemanden haben, der versteht, wie Interna funktionieren, wird es eine Situation geben, in der SQL2020, Windows 15 und Linux 20.04 in einer müllsammelnden virtuellen Maschine geschrieben werden, die über 30 Abstraktionsebenen mit über IDE generiertem Code in JavaScript läuft .

Das ist definitiv nicht das, was ich sehen möchte.

Also ja, das müssen sie auf jeden Fall!


2
Guter Humor! +1 und völlig einverstanden.
Heltonbiker

7

Weder Java noch C # haben Zeiger eliminiert, sie haben Verweise, die fast gleich sind. Was beseitigt wurde, ist Zeigerarithmetik, die in einem Einführungskurs weggelassen werden kann.
Ohne das Konzept von Zeigern oder Referenzen könnte keine nicht-triviale Anwendung durchgeführt werden, daher lohnt es sich zu unterrichten (ohne sie könnte keine dynamische Speicherzuweisung erfolgen).

Beachten Sie Folgendes in C ++ und Java, und ich vermute, es ist nicht sehr unterschiedlich in C #:
aClass *x = new aClass();
aClass x = new aClass();
Es gibt nicht wirklich zu viel Unterschied zwischen Zeigern und Referenzen, oder?
Zeigerarithmetik sollte vermieden werden, sofern dies nicht erforderlich ist, und wenn mit Modellen auf hoher Ebene programmiert wird, so dass dort nicht viele Probleme auftreten.


6

Der professionelle Programmierer sollte Zeiger beherrschen.

Die Leute, die das Programmieren kennenlernen wollen, sollten etwas über das Vorhandensein und die Auswirkungen erfahren, diese aber nicht unbedingt anwenden.

Die Leute, die persönliche Probleme per Programmierung lösen wollen (wie ich, die viele Python-Skripte verwenden), könnten sie durchaus ignorieren.

Na das ist meine meinung ...; o)


3

Variable Adresszeiger sind ein spezieller Fall des allgemeineren Konzepts der Indirektion. Indirektion wird in den meisten (allen?) Modernen Sprachen in vielen Konstrukten wie Delegaten und Rückrufen verwendet. Wenn Sie das Konzept der Indirektion verstehen, wissen Sie, wann und wie Sie diese Tools am besten verwenden können.


3

Absufreakinglutely JA ! Jeder, der programmiert, muss Zeiger und Indirektion verstehen.

Mit Zeigern wird eine große Menge an Datenzugriffen in allen Sprachen ausgeführt. Zeiger sind ein Hardware-Merkmal aller Mikroprozessoren. Hochstufige Sprachen wie Java, VB & C # verhindern im Wesentlichen den direkten Zugriff der Benutzer der Sprache auf Zeiger mit Verweisen. Referenzen verweisen über das Speicherverwaltungsschema der Sprache auf Objekte (z. B. ein Zeiger mit Metadaten oder nur eine Nummer für die Speichertabelle).

Das Verständnis der Funktionsweise von Zeigern ist von grundlegender Bedeutung für die Funktionsweise von Computern. Zeiger sind auch flexibler und leistungsfähiger als Referenzen.

Der Grund, warum Arrays bei Index Null beginnen, liegt beispielsweise darin, dass Arrays eigentlich eine Abkürzung für Zeigerarithmetik sind. Ohne zu lernen, wie Zeiger funktionieren, bekommen viele beginnende Programmierer keine Arrays.

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

Zeile 2 in Zeigerarithmetik wäre:

*(foo + sizeof(int) * 2) = a;

Ohne das Verständnis von Zeigern kann man die Speicherverwaltung, den Stack, den Heap oder sogar Arrays nicht verstehen! Darüber hinaus muss man Zeiger und Dereferenzierung verstehen, um zu verstehen, wie Funktionen und Objekte übergeben werden.

TL: DR : Das Verstehen von Zeigern ist von grundlegender Bedeutung für das Verständnis, dass Computer tatsächlich funktionieren .


2

Ich denke, es läuft darauf hinaus, dass die Notwendigkeit, mit Zeigern umzugehen, wegfiel, da sich die Programmierer weniger mit der direkten Hardware befassten, auf der sie liefen. B. eine verknüpfte Listendatenstruktur so zuzuweisen, dass sie perfekt zu der Sequenz von 640-Byte-Speichermodulen passt, die die spezialisierte Hardware hatte.

Das manuelle Behandeln von Zeigern kann fehleranfällig sein (was zu Speicherverlusten und ausnutzbarem Code führt) und ist zeitaufwendig, um das Richtige zu finden. So verwalten Java und C # usw. jetzt Ihren Speicher und Ihre Zeiger für Sie über ihre virtuellen Maschinen (VMs). Dies ist vermutlich weniger effizient als die Verwendung von Raw-C / C ++, obwohl sich die VMs ständig verbessern.

C (und C ++) sind immer noch weit verbreitete Sprachen, insbesondere in den Bereichen High Performance Computing, Gaming und Embedded Hardware. Ich bin persönlich dankbar, dass ich etwas über Zeiger gelernt habe, da der Übergang zu Javas Referenzen (ähnlich wie bei Zeigern) sehr einfach war und ich nicht verloren war, als ich meine erste NullPointerException sah (die eigentlich eine NullReferenceException heißen sollte, aber ich schweife ab). .

Ich würde raten, sich mit dem Konzept der Zeiger vertraut zu machen, da diese noch immer viele Datenstrukturen usw. untermauern. Wählen Sie dann eine Sprache aus, in der Sie gerne arbeiten, und wissen Sie, dass Sie, wenn etwas wie eine NPE auftaucht, wissen, was wirklich vor sich geht .


0

Das ist die objektive Wahrheit:

Einige Sprachen unterstützen direkten Speicherzugriff (Zeiger), andere nicht. Es gibt für jeden Fall gute Gründe.

  1. Wie hier bereits erwähnt, war die automatische Speicherverwaltung zu Zeiten von C nicht so aufwändig wie heute. Und die Leute waren sowieso daran gewöhnt. Die guten Programmierer hatten damals ein viel tieferes Verständnis für Computerprogramme als für unsere Generation (ich bin 21). Sie haben Lochkarten verwendet und einige Tage auf die Kompilierungszeit auf dem Mainframe gewartet. Sie wussten wahrscheinlich, warum jeder Teil ihres Codes existierte.

  2. Der offensichtliche Vorteil von Sprachen wie C besteht darin, dass Sie Ihr Programm genauer steuern können. Wann Sie tatsächlich benötigen es, in diesen Tagen? Nur beim Erstellen von Infrastrukturanwendungen, z. B. Betriebssystemprogrammen und Laufzeitumgebungen. Wenn Sie nur eine gute, schnelle, robuste und zuverlässige Software entwickeln möchten, ist die automatische Speicherverwaltung häufig die bessere Wahl.

  3. Tatsache ist, dass der direkte Speicherzugriff im Laufe der Softwareentwicklungsgeschichte zumeist missbraucht wurde. Die Leute hatten Programme erstellt, die Speicher verloren haben, und waren aufgrund der redundanten Speicherzuweisung tatsächlich langsamer (in C ist es einfach und üblich, den virtuellen Speicherplatz des Prozesses für jede einzelne Zuweisung zu erweitern).

  4. Heutzutage leisten virtuelle Maschinen / Laufzeiten eine viel bessere Arbeit als 99% der Programmierer beim Zuweisen und Freigeben von Speicher. Darüber hinaus bieten sie Ihnen zusätzliche Flexibilität in dem Ablauf, den Sie für Ihr Programm benötigen, da Sie (meistens) nicht damit beschäftigt sind, den zugewiesenen Speicher zum richtigen Zeitpunkt und am richtigen Ort freizugeben.

  5. Was das Wissen betrifft. Ich finde es bewundernswert, dass Programmierer wissen, wie die Umgebungen, in denen sie programmieren, implementiert sind. Nicht unbedingt bis ins kleinste Detail, aber das große Ganze.

Ich halte es für interessant, zu wissen, wie Zeiger funktionieren (zumindest). Genauso wie zu wissen, wie Polymorphismus umgesetzt wird. Woher kommt Ihr Prozess und wie? Das sind Dinge, die mich persönlich schon immer interessiert haben. Ich kann ehrlich sagen, dass sie mich zu einem besseren Programmierer gemacht haben, aber ich kann nicht sagen, dass sie eine pädagogische Notwendigkeit für jeden sind, der ein guter Programmierer werden möchte. In beiden Fällen wird mehr wissen oft machen Sie besser auf Ihre Arbeit.

  1. So wie ich das sehe, müssen Sie sich auf die richtigen Entwurfs- und Implementierungstechniken konzentrieren, wenn Sie nur eine Anwendung in Java oder C # oder Ähnlichem erstellen müssen. Testbarer Code, sauberer Code, flexibler Code. In dieser Reihenfolge.

Denn selbst wenn Sie nicht alle Details kennen, kann jemand, der dies tut, das, was Sie erstellt haben, in etwas ändern, das einfach eine bessere Leistung erbringt. Und das ist oft keine schwierige Aufgabe, wenn Sie erst einmal ein ordentliches, sauberes und überprüfbares Design haben (und das ist normalerweise der größte Teil der Arbeit).

Wenn ich ein Interviewer wäre, der jemanden für eine hochsprachige Bewerbung einstellen möchte, wären dies die Dinge, an denen ich am meisten interessiert wäre.

Kenntnisse auf niedrigem Niveau sind ein Bonus. Es ist gut für das Debuggen und gelegentlich für das Erstellen etwas besserer Lösungen. Es macht Sie professionell zu einer interessanten Person. Es gewährt Ihnen einen gewissen Respekt an Ihrem Arbeitsplatz.

Aber in der heutigen Welt ist es keine heilige Voraussetzung.


-1

Für die meisten praktischen Zwecke in OO-Hochsprachen ist das Verstehen von Referenzen ausreichend. Sie müssen nicht wirklich verstehen, wie diese Sprachen Referenzen in Bezug auf Zeiger implementieren.

Es gibt viel funktionalere und modernere Multi-Paradigmen-Ansätze, die ich viel höher schätzen würde als die Möglichkeit, ausgefallene Zeiger-Arithmetik zu erstellen, um zu sagen, dass die 1000. optimierte Funktion zum Kopieren von Strings wahrscheinlich schlechter abschneidet als String.copy Ihrer Standard-Bibliothek.

Ich empfehle, zuerst viel mehr verschiedene Konzepte auf höherer Ebene zu lernen und dann Sprachen mit unterschiedlichen Designs zu lernen, um Ihren Horizont zu erweitern, bevor Sie sich auf hardwarenahe Dinge spezialisieren.

Ich sehe oft völlig gescheiterte Versuche, Webservlets oder ähnlichen Code für einen Gewinn von 5% zu optimieren, wenn Caching (Merken), SQL-Optimierung oder nur Webserver-Konfigurationstuning mit geringem Aufwand 100% oder mehr ergeben können. Das Fummeln mit Zeigern ist in den meisten Fällen eine vorzeitige Optimierung .


-1

Auf jeden Fall brauchen wir ein gründliches Zeigerkonzept, wenn Sie wirklich ein guter Programmierer sein wollen. Der Grund für das Pointer-Konzept war ein direkter Zugang zu Ihrem Wert, der mit Zeitbeschränkungen effizienter und effektiver wird ...

In Anbetracht der Tatsache, dass mobile Anwendungen nur über sehr begrenzten Arbeitsspeicher verfügen, müssen wir sie heutzutage sehr sorgfältig verwenden, damit die Benutzerreaktion schnell vonstatten geht. Zu diesem Zweck benötigen wir einen direkten Verweis auf den Wert.

Betrachten Sie Apples Geräte oder die Objective C-Sprache, die ausschließlich mit dem Zeigerkonzept funktioniert. Alle in Ziel C deklarierten Variablen haben Zeiger. Sie müssen das Wiki von Objective C durchgehen


Heutzutage verfügen mobile Apps über mehr Speicher, als in einigen Rechenzentren C vorgesehen ist. Viele mobile Apps sind in Java oder HTML + Javascript geschrieben, alle ohne Verweise (die haben Verweise). Nur ein winziger Bruchteil von sehr spezialisierten Programmierern kann die zugrunde liegenden Betriebssystemschichten erkennen.
Jürgen Strobel
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.