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

17voto

proski Punkte 3263

Ich ziehe es vor, den Wurf zu machen, aber nicht manuell. Mein Favorit ist die Verwendung von g_new y g_new0 Makros von glib. Wenn glib nicht verwendet wird, würde ich ähnliche Makros hinzufügen. Diese Makros reduzieren die Codeduplikation, ohne die Typsicherheit zu beeinträchtigen. Wenn man den Typ falsch wählt, kommt es zu einem impliziten Cast zwischen nicht-void Zeigern, was zu einer Warnung führt (Fehler in C++). Wenn Sie vergessen, den Header einzubinden, der Folgendes definiert g_new y g_new0 würden Sie eine Fehlermeldung erhalten. g_new y g_new0 nehmen beide die gleichen Argumente an, im Gegensatz zu malloc die weniger Argumente benötigt als calloc . Einfach hinzufügen 0 um null-initialisierten Speicher zu erhalten. Der Code kann ohne Änderungen mit einem C++-Compiler kompiliert werden.

16voto

user877329 Punkte 5986

Das Beste, was man bei der Programmierung in C tun kann, ist, wenn es möglich ist:

  1. Lassen Sie Ihr Programm mit einem C-Compiler kompilieren, wobei alle Warnungen aktiviert sind -Wall und beheben Sie alle Fehler und Warnungen
  2. Stellen Sie sicher, dass es keine Variablen gibt, die als auto
  3. Dann kompilieren Sie es mit einem C++-Compiler mit -Wall y -std=c++11 . Beheben Sie alle Fehler und Warnungen.
  4. Kompilieren Sie nun wieder mit dem C-Compiler. Ihr Programm sollte nun ohne jede Warnung kompiliert werden und weniger Fehler enthalten.

Mit diesem Verfahren können Sie die Vorteile der strengen Typüberprüfung von C++ nutzen und so die Anzahl der Fehler reduzieren. Insbesondere zwingt diese Prozedur Sie dazu, die stdlib.h oder Sie erhalten

malloc nicht in diesem Bereich deklariert wurde

und zwingt Sie außerdem dazu, das Ergebnis von malloc oder Sie erhalten

ungültige Konvertierung von void* a T*

oder was auch immer Ihr Zieltyp ist.

Die einzigen Vorteile, die ich beim Schreiben in C anstelle von C++ sehe, sind

  1. C hat eine gut spezifizierte ABI
  2. C++ kann mehr Code erzeugen [Ausnahmen, RTTI, Vorlagen, Laufzeit Polymorphismus]

Beachten Sie, dass der zweite Cons im Idealfall verschwinden sollte, wenn Sie die gemeinsame Teilmenge von C zusammen mit der statisch polymorphes Merkmal.

Für diejenigen, die strenge C++-Regeln unbequem finden, können wir die C++11-Funktion mit abgeleiteten Typen verwenden

auto memblock=static_cast<T*>(malloc(n*sizeof(T))); //Mult may overflow...

23 Stimmen

Verwenden Sie einen C-Compiler für C-Code. Verwenden Sie einen C++-Compiler für C++-Code. Kein Wenn und kein Aber. Ihren C-Code in C++ umzuschreiben, ist eine ganz andere Sache und kann - oder auch nicht - die Zeit und das Risiko wert sein.

4 Stimmen

Ich möchte den Rat von @TobySpeight ergänzen: Wenn Sie C-Code in einem C++-Projekt verwenden müssen, können Sie den C-Code normalerweise als C kompilieren (z. B. gcc -c c_code.c ), der C++-Code als C++ (z. B. g++ -c cpp_code.cpp ), und verbinden sie dann miteinander (z.B.. gcc c_code.o cpp_code.o oder umgekehrt, abhängig von den Projektabhängigkeiten). Nun sollte es keinen Grund mehr geben, auf die netten Funktionen der beiden Sprachen zu verzichten...

1 Stimmen

@user877329 Es ist eine vernünftigere Alternative zum mühsamen Hinzufügen von Casts zum Code, die die Lesbarkeit des Codes verringern, nur um "C++-kompatibel" zu sein.

15voto

Casting ist nur für C++, nicht für C. Wenn Sie einen C++-Compiler verwenden, sollten Sie ihn in einen C-Compiler umwandeln.

13voto

Aashish Kumar Punkte 2599

Das Casting von malloc ist in C unnötig, in C++ jedoch obligatorisch.

Casting ist in C aus folgenden Gründen unnötig:

  • void * wird im Fall von C automatisch und sicher in jeden anderen Zeigertyp umgewandelt.
  • Es kann einen Fehler verbergen, wenn Sie vergessen haben, die <stdlib.h> . Dies kann zu Abstürzen führen.
  • Wenn Zeiger und Ganzzahlen unterschiedlich groß sind, verstecken Sie eine Warnung durch Casting und verlieren möglicherweise Bits der zurückgegebenen Adresse.
  • Wenn der Typ des Zeigers bei seiner Deklaration geändert wird, muss man eventuell auch alle Zeilen ändern, in denen malloc aufgerufen und geworfen wird.

Andererseits kann das Casting die Portabilität Ihres Programms erhöhen, d.h. es ermöglicht die Kompilierung eines C-Programms oder einer Funktion als C++.

10voto

Ein void-Zeiger ist ein generischer Zeiger und C unterstützt die implizite Konvertierung eines void-Zeigers in andere Typen, so dass eine explizite Typisierung nicht erforderlich ist.

Wenn Sie jedoch wollen, dass derselbe Code auf einer C++-Plattform, die keine implizite Konvertierung unterstützt, perfekt kompatibel ist, müssen Sie die Typisierung vornehmen.

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