Frage

Der Wikipedia-Artikel zu ANSI C sagt:

Eines der Ziele des ANSI C-Standardisierungsprozesses bestand darin, eine Obermenge von K&R C (dem ersten veröffentlichten Standard) zu erstellen, die viele der später eingeführten inoffiziellen Funktionen enthält.Das Normungsgremium hat jedoch auch mehrere neue Funktionen aufgenommen, wie etwa Funktionsprototypen (aus der Programmiersprache C++ entlehnt) und einen leistungsfähigeren Präprozessor.Auch die Syntax für Parameterdeklarationen wurde geändert, um den C++-Stil widerzuspiegeln.

Das lässt mich denken, dass es Unterschiede gibt.Allerdings habe ich keinen Vergleich zwischen K&R C und ANSI C gesehen.Gibt es ein solches Dokument?Wenn nicht, was sind die Hauptunterschiede?

BEARBEITEN:Ich glaube, auf dem Cover des K&R-Buches steht „ANSI C“.Zumindest glaube ich, dass die Version, die ich zu Hause habe, das tut.Vielleicht gibt es also keinen Unterschied mehr?

War es hilfreich?

Lösung

Hier kann es zu Verwirrung darüber kommen, was „K&R C“ ist.Der Begriff bezieht sich auf die Sprache, die in der ersten Ausgabe von "The C Programmiersprache" dokumentiert ist. Grob gesagt:die Eingabesprache des Bell Labs C-Compilers um 1978.

Kernighan und Ritchie waren am ANSI-Standardisierungsprozess beteiligt.Der „ANSI C“-Dialekt löste „K&R C“ ab und nachfolgende Ausgaben von „The C Programming Language“ übernehmen die ANSI-Konventionen.„K&R C“ ist eine „tote Sprache“, außer dass einige Compiler immer noch Legacy-Code akzeptieren.

Andere Tipps

Funktionsprototypen waren die offensichtlichste Änderung zwischen K&R C und C89, aber es gab noch viele andere.Auch in die Standardisierung der C-Bibliothek wurde viel Arbeit investiert.Obwohl es sich bei der Standard-C-Bibliothek um eine Kodifizierung der bestehenden Praxis handelte, war sie eine Kodifizierung mehrere bestehende Praktiken, was es schwieriger machte.P.J.Plaugers Buch, Die Standard-C-Bibliothek, ist eine großartige Referenz und erzählt auch einige Details hinter den Kulissen von Warum Die Bibliothek endete so, wie sie war.

Der ANSI/ISO-Standard C ist in vielerlei Hinsicht dem K&R C sehr ähnlich.Es war beabsichtigt, dass der größte Teil des vorhandenen C-Codes ohne große Änderungen auf ANSI-Compilern aufbauen sollte.Entscheidend ist jedoch, dass in der Zeit vor der Standardisierung die Semantik der Sprache von jedem Compiler-Anbieter interpretiert werden konnte.ANSI C führte eine gemeinsame Beschreibung der Sprachsemantik ein, die alle Compiler auf die gleiche Stufe stellte.Heute, etwa 20 Jahre später, kann man das leicht als selbstverständlich betrachten, aber es war eine bedeutende Leistung.

Wenn Sie keine vorstandardisierte C-Codebasis pflegen müssen, sollten Sie größtenteils froh sein, dass Sie sich darüber keine Sorgen machen müssen.Wenn Sie dies tun – oder noch schlimmer, wenn Sie versuchen, ein altes Programm auf modernere Standards zu bringen – dann haben Sie mein Mitgefühl.

Es gibt einige geringfügige Unterschiede, aber ich denke, dass spätere Ausgaben von K&R für ANSI C gedacht sind, sodass es keinen wirklichen Unterschied mehr gibt.
„C Classic“ hatte mangels besserer Begriffe eine etwas andere Art, Funktionen zu definieren, d. h.

int f( p, q, r )  
int p, float q, double r;  
{  
    // Code goes here  
}

Ich glaube, der andere Unterschied waren Funktionsprototypen.Prototypen mussten keine Liste von Argumenten oder Typen annehmen – und das konnten sie auch nicht.In ANSI C ist dies der Fall.

  1. Funktionsprototyp.
  2. konstante und flüchtige Qualifikationsmerkmale.
  3. Breite Zeichenunterstützung und Internationalisierung.
  4. Ermöglicht die Verwendung des Funktionszeigers ohne Dereferenzierung.

Ein weiterer Unterschied besteht darin, dass Funktionsrückgabetypen und Parametertypen nicht definiert werden mussten.Es wird davon ausgegangen, dass es sich dabei um Ganzzahlen handelt.

f(x)
{
    return x + 1;
}

Und

int f(x)
int x;
{
    return x + 1;
}

sind identisch.

  • FUNKTIONSPROTOTYPING: ANSI C übernimmt die C++-Funktionsprototyptechnik, bei der Funktionsdefinition und -deklaration Funktionsnamen, Argumente, Datentypen und Rückgabewertdatentypen umfassen. Funktionsprototypen ermöglichen ANSI-Compilern die Prüfung auf Funktionsaufrufe im Benutzerprogramm, die eine ungültige Anzahl von Argumenten übergeben oder inkompatible Argumentdatentypen. Diese beheben eine große Schwäche der K&R-C-Compiler: Ungültige Aufrufe im Benutzerprogramm bestehen häufig die Kompilierung, führen jedoch zum Absturz des Programms, wenn sie ausgeführt werden

Der Unterschied ist:

  1. Prototyp
  2. Breite Zeichenunterstützung und Internationalisierung
  3. Unterstützung für const- und volatile-Schlüsselwörter
  4. ermöglichen die Verwendung von Funktionszeigern zur Dereferenzierung

Die Hauptunterschiede zwischen ANSI C und K&R C sind folgende:

  • Funktions-Prototyping
  • Unterstützung der Datentypqualifizierer const und volatile
  • unterstützen breite Zeichen und Internationalisierung
  • ermöglichen die Verwendung von Funktionszeigern ohne Dereferenzierung

ANSI C übernimmt die C++-Funktionsprototyptechnik, bei der Funktionsdefinition und -deklaration Funktionsnamen, Datentypen von Argumenten und Datentypen für Rückgabewerte umfassen.Funktionsprototypen ermöglichen es dem ANSI-C-Compiler, in Benutzerprogrammen nach Funktionsaufrufen zu suchen, die eine ungültige Anzahl von Argumenten oder inkompatible Argumentdatentypen übergeben.Diese beheben eine große Schwachstelle des K&R C-Compilers.

Beispiel:to deklariert eine Funktion foo und erfordert, dass foo zwei Argumente annimmt

 unsigned long foo (char* fmt, double data)
 {
      /*body of foo */
 }

Der größte Einzelunterschied besteht meiner Meinung nach im Funktions-Prototyping und in der Syntax zur Beschreibung der Typen von Funktionsargumenten.

Ein wesentlicher Unterschied, den noch niemand erwähnt hat, besteht darin, dass C vor ANSI weitgehend durch Präzedenzfälle und nicht durch Spezifikationen definiert wurde;in Fällen, in denen bestimmte Vorgänge auf einigen Plattformen vorhersehbare Folgen hätten, auf anderen jedoch nicht (z. B.(Verwendung von Vergleichsoperatoren auf zwei unabhängigen Zeigern)) sprach sich der Präzedenzfall stark dafür aus, dem Programmierer Plattformgarantien zur Verfügung zu stellen.Zum Beispiel:

  1. Auf Plattformen, die eine natürliche Rangfolge aller Zeiger auf alle Objekte definieren, könnte man sich darauf verlassen, dass die Anwendung der Vergleichsoperatoren auf beliebige Zeiger diese Rangfolge ergibt.

  2. Auf Plattformen, auf denen die natürliche Methode zum Testen, ob ein Zeiger „größer als“ ein anderer ist, nie einen anderen Nebeneffekt hat als einen wahren oder falschen Wert zu liefern, könnte man sich auch darauf verlassen, dass die Anwendung der Vergleichsoperatoren auf beliebige Zeiger niemals irgendeinen Nebeneffekt hat -andere Auswirkungen als die Erzielung eines wahren oder falschen Werts.

  3. Auf Plattformen, auf denen zwei oder mehr Integer-Typen dieselbe Größe und Darstellung haben, könnte man sich auf einen Zeiger auf einen solchen Integer-Typ verlassen, um Informationen eines anderen Typs mit derselben Darstellung zu lesen oder zu schreiben.

  4. Auf Zweierkomplement-Plattformen, auf denen Ganzzahlüberläufe automatisch stillschweigend umgebrochen werden, kann man sich darauf verlassen, dass sich eine Operation mit vorzeichenlosen Werten, die kleiner als „int“ sind, so verhält, als ob der Wert vorzeichenlos wäre, wenn das Ergebnis zwischen INT_MAX+1u und UINT_MAX liegt wurde weder zu einem größeren Typ hochgestuft noch als linker Operand von verwendet >>, noch einer der Operanden von /, %, oder ein beliebiger Vergleichsoperator. In der Begründung des Standards wird dies übrigens als einer der Gründe genannt, warum kleine unsignierte Typen zu signierten Typen heraufgestuft werden.

Vor C89 war unklar, inwieweit Compiler für Plattformen, auf denen die oben genannten Annahmen von Natur aus nicht gelten würden, diese Annahmen trotzdem aufrecht erhalten würden, aber es gab kaum Zweifel, dass Compiler für Plattformen, die solche Annahmen einfach und kostengünstig aufrechterhalten konnten sollte es tun.Die Autoren des C89-Standards haben sich nicht die Mühe gemacht, dies ausdrücklich zu sagen, weil:

  1. Compiler, deren Autoren nicht absichtlich dumm waren, würden solche Dinge weiterhin tun, wenn es praktisch möglich wäre, ohne dass es ihnen gesagt werden müsste (die Begründung für die Heraufstufung kleiner vorzeichenloser Werte in vorzeichenbehaftete Werte bestärkt diese Ansicht nachdrücklich).

  2. Der Standard forderte nur, dass Implementierungen in der Lage sein mussten, ein möglicherweise erfundenes Programm ohne Stapelüberlauf auszuführen, und erkannte, dass eine stumpfe Implementierung zwar jedes andere Programm so behandeln konnte, als würde es undefiniertes Verhalten aufrufen, hielt es aber nicht für sinnvoll, sich Gedanken über das Schreiben stumpfer Compiler zu machen Implementierungen, die „konform“, aber nutzlos waren.

Obwohl „C89“ gleichzeitig so interpretiert wurde, dass es „die durch C89 definierte Sprache plus alle zusätzlichen Funktionen und Garantien, die die Plattform bietet“ bedeutet, haben die Autoren von gcc eine Interpretation vorangetrieben, die alle Funktionen und Garantien ausschließt, die über die von C89 vorgeschriebenen hinausgehen.

Allen Behauptungen zum Trotz war und ist K&R durchaus in der Lage, von unten bis hin zur Hardware alles Mögliche anzubieten.Das Problem besteht nun darin, einen Compiler (vorzugsweise kostenlos) zu finden, der ein paar Millionen Zeilen von K&R C sauber kompilieren kann, ohne sich damit herumschlagen zu müssen. Und der auf so etwas wie einem AMD-Multicore-Prozessor läuft.

Soweit ich sehen kann, gibt es nach einem Blick auf die Quelle der GCC 4.x.x-Serie keinen einfachen Hack, um die -traditional- und -cpp-traditional-Lag-Funktionalität wieder in ihren vorherigen Betriebszustand zu versetzen, ohne dass mehr Aufwand erforderlich wäre, als ich erwartet habe einstellen.Und es ist einfacher, einen K&R-Pre-ANSI-Compiler von Grund auf zu erstellen.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top