2788 Stimmen

Muss ich das Ergebnis von malloc casten?

En diese Frage schlug jemand in einer Kommentar dass ich no werfen das Ergebnis von malloc . d.h., ich sollte dies tun:

int *sieve = malloc(sizeof(*sieve) * length);

statt:

int *sieve = (int *) malloc(sizeof(*sieve) * length);

Warum sollte dies der Fall sein?

35 Stimmen

9 Stimmen

Gussformen sind böse. Ich sehe so viele Abdrücke im Code, die nur das Ergebnis einer schlechten Programmierpraxis sind. Wann immer Sie einen Cast einfügen müssen, sollten Sie sich als erstes fragen, was hier falsch ist. Ist alles so deklariert, wie es sein sollte? Wenn ja, wäre kein Cast erforderlich, also ist etwas falsch deklariert. Wenn Sie wirklich etwas auf niedriger Ebene mit einzelnen Bytes in einem int oder so tun müssen, ziehen Sie eine Union in Betracht, um auf sie zuzugreifen. Das wird sie genau richtig deklarieren. Als Faustregel gilt: Fügen Sie sie nicht ein, es sei denn, der Compiler beschwert sich. Dann vermeiden Sie sie. Dieses Beispiel wird sich nicht beschweren. void pointer wird zu jedem Typ promoten.

2 Stimmen

@HansLepoeter in C++ sind diese für malloc erforderlich, was meine Vermutung stützt, dass damit etwas nicht stimmt

118voto

PaulJWilliams Punkte 18533

In C können Sie implizit eine void Zeiger auf jede andere Art von Zeiger, so dass ein Cast nicht notwendig ist. Die Verwendung eines Casts kann dem zufälligen Beobachter suggerieren, dass es einen Grund gibt, warum ein Cast erforderlich ist, was irreführend sein kann.

0 Stimmen

Ohne die explizite Angabe des Typs im Deklarator ist der Cast in der Regel häufiger irreführend, da er leicht zwischen der Absicht, ein Objekt zuzuweisen (ohne Interesse am Anfangswert) und lediglich etwas (nicht initialisierten) Speicher zuzuweisen, verwechselt werden kann.

116voto

Lundin Punkte 171916

Sie werfen nicht das Ergebnis von malloc denn dadurch wird Ihr Code unnötig unübersichtlich.

Der häufigste Grund, warum Menschen das Ergebnis von malloc ist, weil sie nicht wissen, wie die Sprache C funktioniert. Das ist ein Warnzeichen: Wenn Sie nicht wissen, wie ein bestimmter Sprachmechanismus funktioniert, dann nicht Raten Sie mal. Schlagen Sie es nach oder fragen Sie auf Stack Overflow.

Einige Kommentare:

  • Ein void-Zeiger kann ohne expliziten Cast in/aus jedem anderen Zeigertyp konvertiert werden (C11 6.3.2.3 und 6.5.16.1).

  • C++ erlaubt jedoch keinen impliziten Cast zwischen void* und einem anderen Zeigertyp. In C++ wäre der Cast also korrekt gewesen. Aber wenn Sie in C++ programmieren, sollten Sie new und nicht malloc() . Und Sie sollten niemals C-Code mit einem C++-Compiler kompilieren.

    Wenn Sie sowohl C als auch C++ mit demselben Quellcode unterstützen müssen, verwenden Sie Compilerschalter, um die Unterschiede zu markieren. Versuchen Sie nicht, beide Sprachstandards mit demselben Code zu unterstützen, da sie nicht kompatibel sind.

  • Wenn ein C-Compiler eine Funktion nicht finden kann, weil Sie vergessen haben, den Header einzubinden, erhalten Sie eine entsprechende Compiler-/Linker-Fehlermeldung. Wenn Sie also vergessen haben, den <stdlib.h> Das ist nicht schlimm, denn dann können Sie Ihr Programm nicht erstellen.

  • Bei alten Compilern, die einer Version des Standards folgen, die mehr als 25 Jahre alt ist, wird vergessen, die <stdlib.h> zu einem gefährlichen Verhalten führen würde. Denn in diesem alten Standard wandelten Funktionen ohne sichtbaren Prototyp den Rückgabetyp implizit in int . Casting des Ergebnisses von malloc würde diesen Fehler dann explizit verbergen.

    Aber das ist wirklich kein Thema. Sie verwenden keinen 25 Jahre alten Computer, warum sollten Sie also einen 25 Jahre alten Compiler verwenden?

14 Stimmen

"Sinnloses Durcheinander" ist eine abschätzige Übertreibung, mit der man niemanden überzeugen kann, der nicht ohnehin schon der gleichen Meinung ist wie man selbst. Ein Guss ist sicherlich nicht sinnlos; Ron Burks und Kaz' Antworten enthalten Argumente für den Guss, denen ich sehr zustimme. Ob diese Bedenken schwerer wiegen als die von Ihnen genannten, ist eine berechtigte Frage. Mir scheinen Ihre Bedenken im Vergleich zu denen der anderen relativ gering zu sein.

1 Stimmen

"Ein void-Zeiger kann ohne explizite Umwandlung in/aus jedem anderen Zeigertyp konvertiert werden" wird von 6.3.2.3 nicht unterstützt. Vielleicht denken Sie an "Zeiger auf einen beliebigen Objekttyp"? "void pointer" und "pointer to a function" sind nicht so leicht konvertierbar.

0 Stimmen

Der Hinweis war in der Tat unvollständig. Der für die "Implizitheit" relevante Teil ist die Regel der einfachen Zuweisung 6.5.16.1. "ein Operand ist ein Zeiger auf einen Objekttyp, und der andere ist ein Zeiger auf eine qualifizierte oder unqualifizierte Version von void". Ich habe diesen Verweis der Vollständigkeit halber in die Antwort eingefügt.

107voto

EFraim Punkte 12426

In C erhalten Sie eine implizite Konvertierung von void * auf einen beliebigen anderen (Daten-)Zeiger.

6 Stimmen

@Jens: OK, vielleicht ist die korrektere Formulierung "implizite Konvertierung". Wie die Verwendung einer Integralvariablen in einem Fließkommaausdruck.

0 Stimmen

@EFraim Das würde tatsächlich zu einer Besetzung führen, und zwar zu einer impliziten.

78voto

Yu Hao Punkte 114970

Umwandlung des Wertes, der von malloc() ist jetzt nicht notwendig, aber ich möchte einen Punkt hinzufügen, auf den anscheinend noch niemand hingewiesen hat:

In den alten Tagen, das heißt, bevor ANSI C bietet die void * als allgemeiner Typ von Zeigern, char * ist der Typ für eine solche Verwendung. In diesem Fall kann der Cast die Compiler-Warnungen ausschalten.

Referenz: C FAQ

5 Stimmen

Compiler-Warnungen abzuschalten ist eine schlechte Idee.

12 Stimmen

@AlbertvanderHorst Nicht, wenn Sie damit genau das Problem lösen, vor dem die Warnung Sie warnen soll.

1 Stimmen

@Dan . Wenn mit der Lösung des genauen Problems gemeint ist, dass ein Unterprogramm umgeschrieben werden muss, um moderne ANSI C-Typen anstelle von char * zurückzugeben, stimme ich zu. Ich würde das nicht als Abschalten des Compilers bezeichnen. Geben Sie nicht den Managern nach, die darauf bestehen, dass es keine Compilerwarnungen gibt, anstatt sie bei jeder Neukompilierung zu verwenden, um mögliche Probleme zu finden. Groetjes Albert

61voto

user3079666 Punkte 1119

Ich füge nur meine Erfahrung hinzu, ich studiere Computertechnik und sehe, dass die zwei oder drei Professoren, die ich in C habe schreiben sehen, immer malloc casten, aber derjenige, den ich gefragt habe (mit einem immensen Lebenslauf und Verständnis von C), sagte mir, dass es absolut unnötig ist, sondern nur verwendet wird, um absolut spezifisch zu sein, und um die Studenten in die Mentalität zu bringen, absolut spezifisch zu sein. Im Grunde ändert Casting nichts an der Funktionsweise, es tut genau das, was es sagt, es weist Speicher zu, und Casting hat keinen Einfluss darauf, man erhält denselben Speicher, und selbst wenn man ihn versehentlich in etwas anderes umwandelt (und irgendwie Compilerfehler umgeht), greift C auf dieselbe Weise darauf zu.

Edit : Das Casting hat einen gewissen Sinn. Wenn Sie die Array-Notation verwenden, muss der erzeugte Code wissen, wie viele Speicherplätze er vorrücken muss, um den Anfang des nächsten Elements zu erreichen, dies wird durch Casting erreicht. Auf diese Weise weiß man, dass man bei einem double um 8 Bytes weitergeht, bei einem int um 4 Bytes usw. Bei der Zeiger-Notation hat dies keine Auswirkungen, bei der Array-Notation ist es jedoch notwendig.

4 Stimmen

Wie bereits erwähnt, kann der Cast jedoch Fehler verbergen und die Analyse des Codes durch den Compiler oder den statischen Analysator erschweren.

3 Stimmen

"Im Grunde genommen wird das Gießen nichts an seiner Funktionsweise ändern. Das Casting auf den passenden Typ sollte nichts ändern, aber sollte sich der Typ der var ändern und das Casting nicht mehr passen, könnten Probleme auftreten? IWOs, der Typ von cast und var sollten synchron gehalten werden - das bedeutet doppelte Wartungsarbeit.

3 Stimmen

Ich kann verstehen, warum Profs das Casting bevorzugen. Casting mag aus pädagogischer Sicht nützlich sein, da es dem Ausbilder Informationen vermittelt und der Code der Studenten nicht gewartet werden muss - es ist Wegwerfcode. Doch vom Standpunkt der Codierung, Peer-Review und Wartung Perspektive, p = malloc(sizeof *p * n); ist so einfach und besser.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X