TL;DR
int *sieve = (int *) malloc(sizeof(int) * length);
hat zwei Probleme. Der Cast und die Tatsache, dass Sie den Typ statt der Variable als Argument für sizeof verwenden. Machen Sie stattdessen Folgendes:
int *sieve = malloc(sizeof *sieve * length);
Lange Fassung
Nein ; Sie nicht werfen das Ergebnis, da:
- Das ist unnötig, denn
void *
wird in diesem Fall automatisch und sicher in jeden anderen Zeigertyp umgewandelt.
- Der Code wird dadurch unübersichtlicher, und Abwandlungen sind nicht sehr leicht zu lesen (insbesondere wenn der Zeigertyp lang ist).
- Das führt dazu, dass man sich wiederholt, was im Allgemeinen schlecht ist.
- Es kann einen Fehler verbergen, wenn Sie vergessen haben, die
<stdlib.h>
. Dies kann zu Abstürzen führen (oder, schlimmer noch, no erst viel später in einem völlig anderen Teil des Codes einen Absturz verursachen). Bedenken Sie, was passiert, wenn Zeiger und Ganzzahlen unterschiedlich groß sind; dann verstecken Sie eine Warnung durch Casting und verlieren möglicherweise Bits der zurückgegebenen Adresse. Anmerkung: seit C99 gibt es keine impliziten Funktionen mehr in C, und dieser Punkt ist nicht mehr relevant, da es keine automatische Annahme mehr gibt, dass nicht deklarierte Funktionen zurückgeben int
.
Zur Klarstellung: Ich sagte "man wirft nicht", nicht "man wirft nicht brauchen zu werfen". Meiner Meinung nach ist es ein Versäumnis, den Wurf einzubeziehen, selbst wenn man ihn richtig gemacht hat. Es gibt einfach keine Vorteile, aber einen Haufen potenzieller Risiken, und die Einbeziehung des Gipses zeigt, dass Sie die Risiken nicht kennen.
Beachten Sie auch, wie Kommentatoren anmerken, dass es sich hier um reines C handelt, nicht um C++. Ich glaube fest an C und C++ als getrennte Sprachen.
Hinzu kommt, dass Ihr Code die Typinformationen unnötigerweise wiederholt ( int
), was zu Fehlern führen kann. Es ist besser, den Zeiger, der zum Speichern des Rückgabewerts verwendet wird, zu de-referenzieren, um die beiden zusammen zu "sperren":
int *sieve = malloc(length * sizeof *sieve);
Dadurch wird auch die length
nach vorne, um die Sichtbarkeit zu erhöhen, und lässt die überflüssigen Klammern mit sizeof
; sie werden nur benötigt wenn das Argument ein Typname ist. Viele Leute scheinen dies nicht zu wissen (oder zu ignorieren), was ihren Code noch langatmiger macht. Zur Erinnerung: sizeof
ist keine Funktion! :)
Während des Umzugs length
nach vorne Mai die Sichtbarkeit in einigen seltenen Fällen zu erhöhen, sollte man auch darauf achten, dass es im allgemeinen Fall besser ist, den Ausdruck als zu schreiben:
int *sieve = malloc(sizeof *sieve * length);
Da die Beibehaltung der sizeof
In diesem Fall wird zunächst sichergestellt, dass die Multiplikation mit mindestens size_t
math.
Vergleichen Sie: malloc(sizeof *sieve * length * width)
vs. malloc(length * width * sizeof *sieve)
die zweite kann die length * width
wenn width
y length
sind kleinere Typen als size_t
.
35 Stimmen
stackoverflow.com/q/7545365/168175
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