Frage

Unser statisches Analyse -Tool beschwert sich über ein "nutzloses Typ -Qualifikationsspiel beim Rückkehrtyp", wenn wir Prototypen in Header -Dateien haben, wie z. B.:

const int foo();

Wir haben es so definiert, weil die Funktion eine Konstante zurückgibt, die sich nie ändern wird, und derkt, dass die API klarer zu sein schien const an Ort und Stelle.

Ich bin der Meinung, dass dies der Klarheit der explizit initialisierenden globalen Variablen ausdrücklich auf Null initialisiert ist, obwohl der C -Standard bereits feststellt, dass alle Globalen auf Null initialisiert werden, wenn sie nicht explizit initialisiert werden. Am Ende des Tages spielt es wirklich keine Rolle. (Aber das statische Analysetool beschwert sich nicht darüber.)

Meine Frage ist, gibt es einen Grund, warum dies ein Problem verursachen könnte? Sollten wir die vom Werkzeug erzeugten Fehler ignorieren, oder sollten wir das Tool zu den möglichen Kosten einer weniger klaren und konsistenten API beruhen? (Es gibt andere zurück const char* Konstanten, mit denen das Tool kein Problem hat.)

War es hilfreich?

Lösung

Es ist normalerweise besser, dass Ihr Code so genau wie möglich beschreibt, was los ist. Sie bekommen diese Warnung, weil die const in const int foo(); ist im Grunde bedeutungslos. Die API scheint nur klarer zu sein, wenn Sie nicht wissen, was die const Schlüsselwort bedeutet. Überlastet keine solche Bedeutung nicht; static ist schon schlimm genug, und es gibt keinen Grund, das Potenzial für mehr Verwirrung hinzuzufügen.

const char * bedeutet etwas anderes als const int tut, weshalb sich Ihr Tool nicht darüber beschwert. Ersterer ist ein Zeiger auf eine konstante Zeichenfolge, was bedeutet, dass jeder Code, der die Funktion zurückruft, diese Typ zurückgibt, nicht versuchen sollte, den Inhalt der Zeichenfolge zu ändern (es kann beispielsweise in ROM enthalten sein). Im letzteren Fall hat das System keine Möglichkeit, die Änderungen der zurückgegebenen Änderungen vorzunehmen int, Das Qualifikationsspiel ist also bedeutungslos. Eine engere Parallele zu den Rückgabetypen wäre:

const int foo();
char * const foo2();

Dies führt dazu, dass Ihre statische Analyse die Warnung angibt. Das Hinzufügen eines Const -Qualifikators zu einem Rückgabewert ist eine bedeutungslose Operation. Es ist nur sinnvoll, wenn Sie einen AA -Referenzparameter (oder einen Rückgabetyp) haben, wie Ihre const char * Beispiel.

Tatsächlich habe ich gerade ein kleines Testprogramm gemacht und GCC warnt sogar explizit vor diesem Problem:

test.c:6: warning: type qualifiers ignored on function return type

Es ist also nicht nur Ihr statisches Analyseprogramm, das sich beschwert.

Andere Tipps

Sie können eine andere Technik verwenden, um Ihre Absicht zu veranschaulichen, ohne die Werkzeuge unglücklich zu machen.

#define CONST_RETURN

CONST_RETURN int foo();

Sie haben kein Problem mit const char * Denn das erklärt einen Zeiger auf ständige Zeichen, nicht auf einen ständigen Zeiger.

Ignorieren const zur Zeit, foo() Gibt einen Wert zurück. Du kannst tun

int x = foo();

und den Wert zuweisen, der von zurückgegeben wird foo() zur Variablen x, in ähnlicher Weise können Sie es tun

int x = 42;

den Wert zuweisen 42 zu variable x.
Aber Sie können das nicht ändern 42 ... oder der Wert, der von zurückgegeben wurde foo(). Sagen, dass der Wert zurückgegeben wurde foo() kann nicht geändert werden, indem die Anwendung des const Schlüsselwort für den Typ von foo() erledigt nichts.

Werte kann nicht sein const (oder restrict, oder volatile). Nur Objekte können Typ -Qualifikatoren haben.


Kontrast zu

const char *foo();

In diesem Fall, foo() Gibt einen Zeiger auf ein Objekt zurück. Das von dem zurückgegebene Wert angezeigte Objekt kann qualifiziert werden const.

Der int wird von zurückgegeben von Kopieren. Es mag eine Kopie einer Const sein, aber wenn es etwas anderes zugeordnet ist, kann etwas aufgrund der Tatsache, dass es zugeordnet war, per Definition nicht eine Konstante sein kann.

Das Schlüsselwort const verfügt über eine spezielle Semantik in der Sprache, während Sie es hier als Kommentar missbrauchen. Anstatt Klarheit hinzuzufügen, deutet es eher auf ein Missverständnis der Sprachsemantik hin.

const int foo() unterscheidet sich sehr von const char* foo(). const char* foo() Gibt ein Array (normalerweise eine Zeichenfolge) zurück, deren Inhalt sich nicht ändern darf. Denken Sie über den Unterschied zwischen:

 const char* a = "Hello World";

und

const int b = 1;

a ist immer noch eine Variable und kann anderen Zeichenfolgen zugeordnet werden, die sich nicht ändern können, während b ist keine Variable. So

const char* foo();
const char* a = "Hello World\n";
a = foo();

ist aber erlaubt

const int bar();
const int b = 0;
b = bar();

ist nicht erlaubt, auch mit dem const Erklärung von bar().

Ja. Ich würde empfehlen, Code "explizit" zu schreiben, weil dies jedem (einschließlich Sie selbst) klar macht, wenn Sie den Code lesen, was Sie gemeint haben. Sie schreiben Code für Andere Programmierer zu lesen, nicht um den Launen des Compiler- und statischen Analysewerkzeugs zu gefallen!

(Sie müssen jedoch darauf achten, dass ein solcher "unnötiger Code" keinen anderen Code generiert wird!)

Einige Beispiele für explizite Codierung Verbesserung der Lesbarkeit/Wartbarkeit:

  • Ich lege Klammern um Teile arithmetischer Ausdrücke, um explizit anzugeben, was ich passieren möchte. Dies macht jedem Leser klar, was ich gemeint habe, und erspart mich, mir Sorgen um Vorrangregeln zu machen (oder ay Fehler zu machen):

    int a = b + c * d / e + f;      // Hard to read- need to know precedence
    int a = b + ((c * d) / e) + f;  // Easy to read- clear explicit calculations
    

  • Wenn Sie in C ++ eine virtuelle Funktion außer Kraft setzen, können Sie sie in der abgeleiteten Klasse deklarieren, ohne "virtuell" zu erwähnen. Jeder, der den Code liest, kann nicht sagen, dass es sich um eine virtuelle Funktion handelt, die katastrophal irreführend sein kann! Sie können das virtuelle Schlüsselwort jedoch sicher verwenden:

    virtual int MyFunc()
    Und dies macht jedem klar, dass diese Methode virtuell ist. (Dieser "C ++ - Syntax -Fehler" wird in C# behoben, indem in diesem Fall das Schlüsselwort "Überschreibung" verwendet wird - mehr Beweise, wenn jemand es benötigt, um das "unnötige virtuelle" zu verpassen, ist eine wirklich schlechte Idee)

Dies sind beide eindeutige Beispiele, bei denen der Code "Unnötiges" Code lesbarer und weniger anfällig für Fehler macht.

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