2016-08-02 34 views
11

Funktionen wie strcpy(), malloc(), strlen() und verschiedene andere akzeptieren ihre Argumente oder Rückgabewerte als size_t anstelle eines int oder einer unsigned int aus offensichtlichen Gründen.Warum akzeptiert fgets einen int anstelle einer size_t?

Einige Dateifunktionen wie fread() und fwrite() verwenden Sie auch size_t. In Erweiterung wird erwartet, dass char* fgets (char *str, int num, FILE *stream) ein size_t und nicht ein int als Argument für seine Puffergröße verwenden sollte.

Jedoch verwendet fgets() eine int. Gibt es eine objektive Erklärung warum?

+12

In der C-Standardbibliothek gibt es keine Konsistenz. Funktionen haben sich im Laufe der Zeit entwickelt. 'size_t' hat vielleicht nicht existiert, als' fgets' eingeführt wurde (nur meine Vermutung). – user694733

+1

https://groups.google.com/forum/#!topic/comp.std.c/FnENEIlCidg – artm

+3

Hysterische Rosinen. Wahrscheinlich wurde eine frühe Implementierung von (vor der Standardisierung) verwendet, um "int" zu verwenden, und es wurde nach "Kompatibilität" weitergeführt, wenn C standardisiert wurde. Und ich stimme ab, als * auf der Meinung von Meinungen * zu schließen. –

Antwort

9

Das Original K & R definiert fgets() auf S.155 mit einem int Argument. Der im Buch vorgestellte Code hätte auch mit unsigned int funktioniert (es benutzt >0, aber die Schleife ist so geschrieben, dass sie nie unter Null geht).

size_t wurde später eingeführt, in C89 (ANSI C), als der Typ von sizeof(). Da dieses Feature speziell zur Harmonisierung der Speicherzuordnung eingeführt wurde, wurden die Speicherfunktionen und String-Funktionen entsprechend aktualisiert. Aber Datei-E/A war nicht: die einzigen Dateifunktionen, die in C89 size_t verwendeten, sind die neuen eingeführt von C89 und nicht vorhanden in K & R wie zum Beispiel fread()/fwrite(). Ja, K & R hatte nicht diese Funktionen und stützte sich für bloc-Operationen nur auf (nicht portable) Unix-Lese-/Schreibfunktionen mit Dateideskriptoren.

Es ist zu beachten, dass die POSIX standard, die die Unix-Funktionen harmonisiert, parallel zu der ANSI-C-Standard und issued late 1988 entwickelt wurde. Dieser Standard hat viele Unix-Funktionen zur Verwendung size_t harmonisiert, so dass read()/write() heutzutage mit size_t definiert sind. Aber für die C-Standardbibliothek Funktionen wie fgets(), gibt POSIX Vorrang die C-Standard (Wortlaut der aktuellen Version des Standard):

Die Funktionalität auf dieser Referenzseite beschrieben mit dem ISO-C-Standard ausgerichtet ist, . Ein Konflikt zwischen den hier beschriebenen Anforderungen und der ISO C-Norm ist nicht beabsichtigt.

in POSIX So auch ironischerweise fgets() noch int von seinem historischen K & R geerbt.


Edit: zusätzliche Lese

stdio.h: Dieser Header definiert und prototypisiert die meisten der in Kapitel 7 von K &R aufgeführten Funktionen. Wenige, wenn überhaupt, Änderungen wurden in den Definitionen vorgenommen, die in K & R gefunden wurden, aber einige neue Funktionen wurden hinzugefügt.

+0

Haben Sie eine Idee, ob irgendwelche bemerkenswerten Prä-C89-Implementierungen von fgets vorhersagbar waren, wenn sie einen negativen Wert [z. vorhersagbar behandelt es wie Null, vorhersagbar nichts zu tun, Lesen von-Bytes Daten, aber die Newline, etc. auslassen? Wenn dies der Fall ist, könnte die Änderung von size_t den Implementierungen die Unterstützung dieser Funktion verbieten, es sei denn, die Länge war auf SIZE_T_MAX-UINT_MAX beschränkt. Eine größere Länge als die Puffergröße ist definiert, sofern ein Zeilenumbruch vor dem Ende erfolgreich gelesen wurde der Puffer]. – supercat

+1

Die Implementierung von K & R stammt aus dem Jahr 1978. Da es eine Ganzzahl mit Vorzeichen ist und die erste Schleifenbedingung '--n> 0' ist, würde es anhalten und den Null-Terminator in den Puffer setzen. So völlig vorhersehbar. Wenn der Parameter nicht vorzeichenbehaftet ist, könnte derselbe Code einen Pufferüberlauf verursachen, würde jedoch nach der maximalen UINT_MAX-Iteration anhalten (es sei denn, die Hardware würde das Spiegeln des Vorzeichenbits erfassen). Dann hätte es auch andere Implementierungen geben können: Vor 89 gab es viele Compilerhersteller, von denen die meisten heute nicht mehr bekannt sind ;-). – Christophe

+0

@supercat Ich konnte meinen ehemaligen Lattice C Compiler von 1986 ([acquired by Microsoft] (https://en.wikipedia.org/wiki/Lattice_C)) mit der Quelle seiner Standardbibliothek zurückfinden. 'fgets()' wird mit 'for (i = 0; i Christophe