Muss ich C lernen, um zu verstehen, wie ein Computer funktioniert?

Ich habe oft gehört, dass Leute vorschlagen, C. zu studieren, um die Computerleistung zu verstehen. Ist das eine gute Idee? Sind sie sicher? Ich werde die Schlussfolgerungen des Artikels sofort skizzieren, nur um absolute Klarheit zu schaffen:

  • In C funktioniert der Computer nicht.
  • Ich glaube nicht, dass die meisten Leute wörtlich sprechen, also spielt es keine Rolle.
  • Wenn Sie den Kontext verstehen, kann das Lernen von C aus diesem Grund abhängig von Ihren Zielen immer noch sinnvoll sein.

Ich habe vor, zwei weitere Artikel mit einer detaillierteren Erläuterung der Schlussfolgerungen zu schreiben, aber das reicht bereits aus. Fügen Sie hier Links hinzu, wenn die Artikel erscheinen.

Ich habe oft von Leuten gehört:

Wenn Sie C studieren, können Sie verstehen, wie Computer funktionieren.

Ich denke nicht, dass die Idee anfangs falsch ist, aber sie hat einige Vorbehalte. Wenn Sie sie im Auge behalten, könnte dies eine praktikable Strategie sein, um neue und wichtige Dinge zu lernen. Ich sehe jedoch selten Leute, die diese Vorbehalte ausführlich diskutieren. Deshalb schreibe ich diesen Artikel, um meiner Meinung nach einen sehr notwendigen Kontext zu bieten ... Wenn Sie darüber nachdenken, C zu lernen, um zu verstehen, wie Ihr Computer funktioniert, dann ist dieser Artikel für Sie. Ich hoffe, sie hilft dir dabei, es herauszufinden.

Bevor wir wirklich anfangen, möchte ich noch etwas sagen: Wenn Sie C lernen wollen, dann lernen Sie! Lernen ist großartig. Das Erlernen von C ist für mein Verständnis von Computer und meine Karriere sehr wichtig geworden. Das Erlernen dieser Sprache und ihres Platzes in der Geschichte einer Programmiersprache macht Sie zu einem besseren Programmierer. Sie brauchen keine Entschuldigung. Lerne Dinge nur um zu lernen. Dieser Artikel soll eine Richtlinie sein, um die Wahrheit zu verstehen. Er behandelt nicht, ob C studiert werden soll oder nicht.

Zunächst einmal, wem diese Idee allgemein empfohlen wird. Wenn Sie versuchen, „herauszufinden, wie Computer funktionieren“, ist es selbstverständlich, dass Sie dies derzeit nicht verstehen. Welche Programmierer verstehen nicht, wie Computer funktionieren? Ich habe im Grunde gesehen, dass dieses Gefühl von Leuten kommt, die hauptsächlich in dynamisch getippten „Skriptsprachen“ wie Ruby, Python oder JavaScript programmieren. Sie wissen angeblich nicht, wie Computer funktionieren, weil diese Sprachen in einer virtuellen Maschine funktionieren, in der nur die Semantik der virtuellen Maschine eine Rolle spielt. Letztendlich besteht die gesamte Idee einer virtuellen Maschine darin, Portabilität bereitzustellen. Das Ziel besteht nicht darin, von den Geräten abhängig zu sein, auf denen die VM ausgeführt wird.

Es gibt nur ein Problem: C funktioniert auch in einer virtuellen Maschine.

Abstrakte Maschine C.


Aus Spezifikation C99 , Abschnitt 5.1.2.3, „Programmausführung“:

Die semantischen Beschreibungen in dieser Internationalen Norm beschreiben das Verhalten einer abstrakten Maschine, bei der Optimierungsprobleme nicht relevant sind.

Meiner Meinung nach ist dies beim Lernen von C am wichtigsten. Die Sprache beschreibt nicht „wie ein Computer funktioniert“, sondern wie eine „abstrakte C-Maschine“ funktioniert. Alles andere Wichtige ergibt sich aus diesem Konzept.

Noch ein Hinweis: Hier habe ich C99 gewählt, was nicht der neueste C-Standard ist. Warum? Nun, MSVC hat ... interessante C-Sprachunterstützung und ich bin heutzutage ein Windows-Benutzer. Ja, Sie können clang und gcc unter Windows ausführen. Es gibt keinen so großen Unterschied zwischen C89, C99 und C11, was das betrifft, worüber wir sprechen. Irgendwann muss man sich entscheiden. Die hier erwähnte Version enthält einige Änderungen an der ursprünglichen Spezifikation.

Möglicherweise haben Sie in Ihrem C-Vortrag einen anderen Satz gehört: „C ist ein tragbarer Assembler.“ Wenn Sie über diesen Satz nachdenken, werden Sie verstehen, dass C nicht dem Betrieb eines Computers entsprechen kann, wenn dies zutrifft: Es gibt viele verschiedene Computer mit unterschiedlichen Architekturen. Wenn C wie ein Assembler ist, der auf verschiedenen Computern mit unterschiedlichen Architekturen ausgeführt wird, kann es nicht gleichzeitig genau wie jeder dieser Computer funktionieren. Er muss die Details verbergen, sonst ist er nicht tragbar!

Trotzdem denke ich, dass diese Tatsache keine Rolle spielt, da sich die Leute kaum wörtlich auf "C ist, wie der Computer funktioniert" beziehen. Bevor wir darauf zurückkommen, sprechen wir über die abstrakte C-Maschine und warum viele diesen Aspekt von C nicht zu verstehen scheinen.

Exkurs: Warum irren sich die Menschen?


Ich kann nur über meine Erfahrungen sprechen, obwohl es sicher nicht einzigartig ist.

Ich habe GW-BASIC gelernt, dann C, dann C ++, dann Java. Ich habe von Java gehört, bevor ich ungefähr 1999, vier Jahre nach seinem Erscheinen, anfing, es zu schreiben. Das Marketing stellte zu dieser Zeit Java und C ++ aktiv gegenüber und konzentrierte sich auf die JVM als Plattform und auf die Tatsache, dass das Maschinenmodell sie von C ++ unterscheidet, weshalb C. Sun Microsystems nicht mehr existiert, aber der Spiegel der Pressemitteilung erinnert uns daran:

Java-Anwendungen sind plattformunabhängig. Sie müssen nur die Java Virtual Machine auf jede Plattform portieren. Es fungiert als Interpreter zwischen dem Computer des Benutzers und der Java-Anwendung. Eine in der Java-Umgebung geschriebene Anwendung kann überall funktionieren, sodass Anwendungen nicht mehr auf mehrere Plattformen portiert werden müssen.

Das Hauptmotto war "Einmal schreiben, überall laufen". Diese beiden Sätze haben gezeigt, wie ich (und viele andere) Java verstanden habe und wie es sich von C ++ unterscheidet. Java hat einen Interpreter, eine virtuelle Java-Maschine. In C ++ gibt es keine virtuelle Maschine.

Mit solch einem leistungsstarken Marketing ist die „virtuelle Maschine“ in den Köpfen vieler Menschen zum Synonym für „eine große Laufzeit und / oder einen großen Interpreter“ geworden. Sprachen ohne diese Funktion waren zu stark an einen bestimmten Computer gebunden und mussten portiert werden, da sie nicht wirklich plattformunabhängig waren. Der Hauptgrund für die Existenz von Java war eine Änderung dieses C ++ - Fehlers.

"Laufzeitumgebung", "virtuelle Maschine" und "abstrakte Maschine" sind unterschiedliche Wörter für dasselbe Grundkonzept. Seitdem haben sie jedoch aufgrund einer geringfügigen Abweichung bei der Umsetzung dieser Ideen unterschiedliche Konnotationen erhalten.

Ich persönlich glaube, dass dieses Marketing von 1995 der Grund ist, warum Programmierer die Natur von C immer noch falsch verstehen.

Ist diese Aussage also falsch? Warum sollte Sun Microsystems Millionen und Abermillionen Dollar für die Förderung von Lügen ausgeben? Wenn C auch auf einer abstrakten Maschine basiert, die plattformübergreifende Portabilität bietet, warum benötigen wir Java? Ich denke, dies ist der Schlüssel zum Verständnis dessen, was Menschen wirklich meinen, wenn sie sagen: "C ist, wie der Computer funktioniert."

Was meinen die Leute wirklich?


Obwohl C im Kontext einer virtuellen Maschine arbeitet, unterscheidet es sich immer noch erheblich von Java-ähnlichen Sprachen. Sun hat nicht gelogen. Um zu verstehen, müssen Sie die Geschichte von C kennen.

1969 schrieb Bell Labs ein Computer-Betriebssystem in Assemblersprache. 1970 wurde es UNIX genannt. Im Laufe der Zeit kaufte Bell Labs immer mehr neue Computer, einschließlich des PDP-11.

Als es an der Zeit war, Unix auf PDP-11 zu portieren, entschieden sie sich für eine höhere Sprache, was zu dieser Zeit eine ziemlich radikale Idee war. Stellen Sie sich vor, ich werde Ihnen heute sagen: „Ich werde ein Betriebssystem in Java schreiben“ - Sie werden wahrscheinlich lachen, obwohl die Idee realisierbar ist . Die Situation (nach meinem Verständnis habe ich damals nicht gelebt) war ungefähr dieselbe. Wir haben eine Sprache namens B in Betracht gezogen, die jedoch einige der Funktionen des PDP-11 nicht unterstützte. Daher haben sie einen Nachfolger geschaffen, indem sie ihn "C" nannten, da dies der nächste Buchstabe im Alphabet war.

Es gab keine Sprache "A"; B war erfolgreich mit BCPL (Basic Combined Programming Language).

1972 wurde der erste C-Compiler auf PDP-11 geschrieben und gleichzeitig UNIX in C umgeschrieben. Anfangs dachten sie nicht über Portabilität nach, aber C wurde berühmt, sodass C-Compiler auf andere Systeme portiert wurden.

1978 erschien die erste Ausgabe des Buches "Programmiersprache C". Das liebevoll als "K & R" bezeichnete Buch ähnelte nach den Namen seiner Autoren überhaupt nicht der Spezifikation, sondern beschrieb gleichzeitig die Sprache hinreichend detailliert, wodurch auch andere versuchten, Compiler C zu schreiben. Später wird diese "Version" "K & R C" genannt.

Als sich UNIX und C verbreiteten, wurden beide auf viele Computer portiert. In den 70er und 80er Jahren wuchs ihre Hardware-Basis ständig. Genauso wie C erstellt wurde, weil B nicht alle Funktionen von PDP-11 unterstützte, verwendeten viele Compiler Spracherweiterungen. Da es nur K & R und keine Spezifikation gab, wurde dies als akzeptabel angesehen, solange die Erweiterungen ziemlich nahe beieinander lagen. Bis 1983 verursachte das Fehlen jeglicher Standardisierung Probleme, weshalb ANSI ein Team zusammenstellte, um die Spezifikation vorzubereiten. 1989 kam der C89-Standard heraus, der manchmal als "ANSI C" bezeichnet wird.

Spezifikation C hat versucht, diese verschiedenen Implementierungen auf verschiedener Hardware zu vereinheitlichen. Somit ist die abstrakte C-Maschine eine Art kleinstmögliche Spezifikation, die es ermöglichen würde, dass derselbe Code auf allen Plattformen gleich funktioniert. C-Implementierungen wurden kompiliert, nicht interpretiert, daher gab es keinen Interpreter, daher gab es keine „VM“ im Sinne von 1995. C-Programme werden jedoch auf diesem abstrakten, nicht vorhandenen Computer geschrieben, und dann wird der Code in einen Assembler konvertiert, der für den bestimmten Computer spezifisch ist, auf dem das Programm ausgeführt wird. Sie können sich beim Schreiben von portablem C-Code nicht auf bestimmte Details verlassen. Dies macht das Schreiben von portablem C sehr schwierig, da Sie beim Schreiben der ersten Version Ihres Codes möglicherweise eine plattformspezifische Annahme getroffen haben.

Dies lässt sich am besten anhand eines Beispiels veranschaulichen. Einer der Hauptdatentypen in C ist char , vom Wort "Zeichen". Die abstrakte C-Maschine bestimmt jedoch nicht, wie viele Bits in char . Nun, bestimmt, aber nicht nach Anzahl; Es bestimmt die Größe von CHAR_BIT , die eine Konstante ist. Abschnitt 5.2.4.2.1 der Spezifikation:

Die unten angegebenen Werte sollten durch konstante Ausdrücke ersetzt werden, die für die Vorverarbeitungsanweisungen #if geeignet sind oder verwendet werden. ... Die Werte in bestimmten Implementierungen sollten gleich oder größer (absoluter Wert) der hier angegebenen Werte mit demselben Vorzeichen sein.

CHAR_BIT: 8

Mit anderen Worten, Sie wissen, dass char mindestens 8 Bit beträgt, die Implementierungen jedoch möglicherweise größer sind. Um eine "abstrakte C-Maschine" richtig zu codieren, muss bei der Verarbeitung von char CHAR_BIT anstelle von 8 als Größe verwendet werden. Dies ist jedoch keine Art von Interpreterfunktion, da wir an virtuelle Maschinen denken. Dies ist eine Eigenschaft, wie der Compiler Quellcode in Maschinencode übersetzt.

Ja, es gibt Systeme, bei denen CHAR_BIT nicht 8 .

Daher ist diese "abstrakte Maschine", obwohl technisch dieselbe Idee wie die virtuelle Java-Maschine, eher ein Kompilierungskonstrukt zum Verwalten von Compilern beim Erstellen von Assembler-Code als eine Art Laufzeitprüfung oder -eigenschaft. Der äquivalente Typ in Java ist ein byte , das immer 8 Bit beträgt, und die JVM-Implementierung hat die Aufgabe, was auf Plattformen mit mehr Bytes zu tun ist. (Ich bin mir nicht sicher, ob die JVM auf einer dieser Plattformen funktioniert, aber so sollte es funktionieren.) Die abstrakte C-Maschine wurde als minimaler Wrapper für verschiedene „Hardware“ erstellt und nicht als eine Art Plattform aus festem Stoff, die in Software für Ihren Code geschrieben wurde.

Obwohl Sun technisch falsch war, bedeuten sie in der Praxis ein wenig von dem, was sie wörtlich sagen, und was sie bedeuten, ist wahr. Gleiches gilt für den Satz „Lernen Sie C, um zu verstehen, wie Computer funktionieren“.

Lernen Sie C, um besser zu verstehen, wie Computer funktionieren


Was meinen die Leute wirklich ? Im Zusammenhang mit „sollte ein Rubist C lernen, um zu verstehen, wie Computer funktionieren“ - dies ist ein Ratschlag, „auf das Eisenniveau“ zu gehen. Das heißt, nicht nur zu verstehen, wie Ihr eigenes Programm in der virtuellen Maschine funktioniert, sondern auch, wie die Kombination aus Programm und VM im Kontext der Maschine selbst funktioniert.

Wenn Sie C lernen , erhalten Sie mehr Details, da die abstrakte Maschine sowohl der Hardware als auch den Abstraktionen der Betriebssysteme viel näher kommt. Die C-Sprache unterscheidet sich stark von Hochsprachen, so dass das Lernen viel lehren kann.

Es ist jedoch wichtig, sich daran zu erinnern, dass C im Wesentlichen eine Hardware- Abstraktion ist und Abstraktionen nicht perfekt sind. Seien Sie vorsichtig, was C macht oder wie es mit der Maschine selbst funktioniert. Wenn Sie zu tief gehen, werden Sie sicherlich auf diese Unterschiede stoßen, die Probleme verursachen können. Die meisten Schulungsressourcen für C, insbesondere heute, wenn die Geräte homogener werden, fördern die Idee, dass ein Computer so funktioniert. Daher kann es für einen Schüler schwierig sein zu verstehen, was unter der Haube geschieht und welche Abstraktion von C.

In dieser Diskussion haben wir nicht einmal andere Themen angesprochen. Zum Beispiel ist die Hardware aufgrund der enormen Beliebtheit von C einheitlicher geworden, da sie sich tendenziell der Semantik der abstrakten C-Maschine nähert. Wenn sich Ihre Architektur zu stark von der C-Semantik unterscheidet, können C-Programme viel langsamer als andere ausgeführt werden. und die Hardwaregeschwindigkeit wird oft durch Tests in C gemessen. Dieser Artikel ist bereits ziemlich lang ...

Aus diesem Grund denke ich, dass eine genauere Version dieser Aussage lautet: „Wenn Sie C lernen, lernen Sie mehr über die Funktionsweise von Computern.“ Ich denke wirklich, dass eine ungefähre Bekanntschaft mit C für viele Programmierer nützlich ist, auch wenn sie selbst kein C schreiben. Die Einführung von C gibt Ihnen auch einen Eindruck von der Geschichte unserer Branche.

Es gibt andere Möglichkeiten, dieses Thema zu untersuchen. C ist von Natur aus nicht dafür gedacht, etwas über einen Computer zu lernen, aber es ist eine gute Option.

In der Programmierung gibt es so viel zu lernen. Ich wünsche Ihnen viel Erfolg auf dieser Reise.

Source: https://habr.com/ru/post/de426993/


All Articles