Der einzige "Fehler" ist, dass das Verhalten und die Anforderungen der Funktion nicht eindeutig dokumentiert sind.
Wenn die Dokumentation besagt, dass das Argument ein gültiger Zeiger auf eine Zeichenfolge sein muss (die definitionsgemäß null-terminiert sein muss), dann ist die Funktion korrekt, soweit ich das beurteilen kann (naja, fast - siehe unten) und es liegt in der Verantwortung des Anrufers, ein korrektes Argument zu übergeben. Die C-Standardbibliothek ist voll von String-Funktionen, die sich so verhalten.
Wenn in der Dokumentation angegeben wird, dass die Funktion selbst für die Überprüfung eines gültigen Arguments verantwortlich ist, muss (1) genau angegeben werden, was die Anforderungen sind und (2) wie sich die Funktion bei einem ungültigen Argument verhalten soll.
Es kann leicht auf msg == NULL
überprüfen - aber dann müssen Sie angeben, was es tun soll, wenn das passiert.
Es kann prüfen, auf das Vorhandensein eines '\0'
Terminator innerhalb der ersten Zeichen N - aber dann müssen Sie den Wert von N angeben irgendwie (anscheinend der Autor erwartet einen zusätzlichen Längenparameter) und Sie zu sagen haben, wie Die Funktion sollte sich dann verhalten.
Es kann nicht nach einem ungültigen Nicht-Null-Argument suchen. Beispielsweise könnte ein Aufrufer einen Zeiger übergeben, der nicht initialisiert wurde oder der an free()
übergeben wurde. Es gibt keinen tragbaren (und wahrscheinlich keinen nicht portablen) Weg, die Funktion auf diese Art von Fehler zu überprüfen.
Wenn die Funktion geändert wird, um ein Längenargument zu verwenden (was eine durchaus sinnvolle Änderung ist, die die Verwendung der Funktion sicherer macht), kann sie dennoch nicht alle möglichen Fehlerzustände prüfen. Ein Aufrufer könnte ein Längenargument übergeben, das nicht mit der Länge des tatsächlichen Arrays übereinstimmt. Es liegt immer noch in der Verantwortung des Anrufers, tolower
korrekt anzurufen. Eine Spezifikation für eine Funktion ist ein Vertrag zwischen dem Anrufer und dem Angerufenen. Beide Seiten müssen die Spezifikation erfüllen. In Ermangelung einer solchen Spezifikation (über die Funktionsdeklaration hinaus, die uns einige Informationen gibt, aber nicht genug), ist es sehr schwierig zu sagen, dass die Funktion einen "Fehler" hat. Ein kleiner Punkt: Ich fand tatsächlich, was wahrscheinlich ist ein echter Fehler in der Funktion. Die Funktion toupper()
übernimmt ein Argument vom Typ int
, dessen Wert entweder gleich EOF
oder im Bereich 0
bis UCHAR_MAX
sein muss. Wenn die Ebene char
standardmäßig signiert ist, ist es möglich, einen gültigen char
Wert zu haben, der negativ und ungleich EOF
ist. Das Ergebnis ist ein nicht definiertes Verhalten. Das Update für das ist das Argument zu unsigned char
würfen
printf("%c", toupper((unsigned char)msg[i]));
(Der EOF
Sonderfall ist hier nicht relevant.)
Nun, da nicht wirklich ein Bug sein könnte. In Ermangelung einer Spezifikation könnten wir annehmen, dass die Zeichenfolge nur Zeichen mit nicht-negativen Werten enthalten sollte. Eine solche Einschränkung sollte jedoch ausdrücklich erwähnt werden.
Es gibt auch ein mögliches Portabilitätsproblem: je nach System könnte es möglich sein, eine Zeichenfolge länger als INT_MAX
Bytes zu haben. Making i
a size_t
anstatt eine int
würde dieses (zugegebenermaßen unwahrscheinliche) Problem vermeiden. Auch dies könnte als implizite Einschränkung betrachtet werden - solche Einschränkungen sollten jedoch, wann immer möglich, explizit gemacht werden.
Schließlich ist die Funktion so definiert, dass sie ein int
Ergebnis zurückgibt, aber sie gibt immer 0
zurück. Es könnte sinnvoll sein, den Rückgabewert als Fehlerindikator zu verwenden. Eine allgemeine Konvention besteht darin, 0
für Erfolg, nicht Null für Fehler zurückzugeben. Wenn diese Version der Funktion als Grundlage für eine verbesserte Version gedacht ist, die mehr Fehlerprüfungen durchführt, ist die Rückgabe eines int
Ergebnisses sinnvoll. Aber dann sollte es eine Spezifikation dessen geben, was dieses Ergebnis bedeutet.
Ähm, verstehst du * was ein Null-Fehler ist? Weil das genau die Definition von einem ist? –
"Da die Schleife endet, wenn ein Nullzeichen vorhanden ist." Ja, aber was ist, wenn ** nicht ** ist? –
@ MarcusMüller, wenn da nicht der String nicht fertig ist. Wie ist der vorgeschlagene Weg? – drdot