Ich arbeite an einer alten Codebasis und so ziemlich jeder Aufruf von free () verwendet eine Besetzung für sein Argument. Beispielsweise,
free((float *)velocity);
free((float *)acceleration);
free((char *)label);
Dabei ist jeder Zeiger vom entsprechenden (und übereinstimmenden) Typ. Ich sehe überhaupt keinen Sinn darin. Es ist sehr alter Code, also frage ich mich, ob es eine K & R-Sache ist. Wenn ja, möchte ich tatsächlich die alten Compiler unterstützen, die dies möglicherweise erforderlich gemacht haben, daher möchte ich sie nicht entfernen.
Gibt es einen technischen Grund, diese Abgüsse zu verwenden? Ich sehe nicht einmal einen pragmatischen Grund, sie zu benutzen. Was bringt es, uns kurz vor dem Freigeben an den Datentyp zu erinnern?
EDIT: Diese Frage ist kein Duplikat der anderen Frage. Die andere Frage ist ein Sonderfall dieser Frage, der meiner Meinung nach offensichtlich ist, wenn die engen Wähler alle Antworten lesen würden.
Kolophon: Ich gebe der "konstanten Antwort" das Häkchen, weil dies ein guter Grund ist, warum dies möglicherweise getan werden muss. Die Antwort darauf, dass es sich um einen Pre-ANSI C-Brauch handelt (zumindest bei einigen Programmierern), scheint jedoch der Grund zu sein, warum er in meinem Fall verwendet wurde. Viele gute Punkte von vielen Leuten hier. Vielen Dank für Ihre Beiträge.
void*
C vor dem Standard, sondern nurchar*
. Wenn Ihre archäologischen Funde also Code enthüllen, der den Parameter in free () umwandelt, muss er meiner Meinung nach entweder aus dieser Zeit stammen oder von einer Kreatur aus dieser Zeit geschrieben worden sein. Ich kann jedoch keine Quelle dafür finden, daher werde ich nicht antworten.Antworten:
Casting kann erforderlich sein, um Compiler-Warnungen aufzulösen, wenn die Zeiger vorhanden sind
const
. Hier ist ein Beispiel für Code, der eine Warnung auslöst, ohne das Argument free freizugeben:Und der Compiler (gcc 4.8.3) sagt:
Wenn Sie
free((float*) velocity);
den Compiler verwenden, hört er auf, sich zu beschweren.quelle
float*
vor dem Befreien gewirkt hat . Ich habe esfree((void *)velocity);
mit gcc 4.8.3 versucht . Natürlich würde es mit einem alten Compiler nicht funktionierenconst char *p
als Argument verwendet und dann freigegeben wird, ist es nicht richtigp
,char*
vor dem Aufruf von free zu konvertieren. Es ist nicht zu deklarieren, dass esconst char *p
an erster Stelle steht, da es modifiziert*p
und entsprechend deklariert werden sollte. (Und wenn es einen const-Zeiger anstelle eines Zeigers auf const braucht ,int *const p
müssen Sie nicht umwandeln , da dies tatsächlich legal ist und daher ohne diePre-Standard C hatte nein,
void*
aber nurchar*
, also mussten Sie alle übergebenen Parameter umwandeln. Wenn Sie auf alten C-Code stoßen, finden Sie möglicherweise solche Casts.Ähnliche Frage mit Referenzen .
Als der erste C-Standard veröffentlicht wurde, wechselten die Prototypen für malloc und free von den
char*
zu denvoid*
heute noch vorhandenen.Und natürlich sind solche Abgüsse in Standard C überflüssig und beeinträchtigen nur die Lesbarkeit.
quelle
free
auf den gleichen Typ umwandeln, der es bereits ist?free
in Standard C funktionieren (Sie müssen nicht umwandeln). Ich habe die 1. Ausgabe nicht gelesen, daher kann ich nicht sagen, ob sie auch in den 80er Jahren vor dem Standard verwirrt waren.void*
, aber es gab auch keine Funktionsprototypen, so dass das Casting des Arguments vonfree
selbst in K & R immer noch nicht erforderlich war (vorausgesetzt, alle Datenzeigertypen verwendeten dieselbe Darstellung).char *
. Welchen Sinn würde es in alten Compilern ohne machenvoid
? Was würden solche Casts erreichen?Hier ist ein Beispiel, bei dem Free ohne Besetzung fehlschlagen würde:
In C können Sie eine Warnung erhalten (eine in VS2012). In C ++ wird eine Fehlermeldung angezeigt.
Abgesehen von seltenen Fällen bläht das Casting nur den Code auf ...
Bearbeiten: Ich habe gegossen, um den Fehler
void*
nichtint*
zu demonstrieren. Es funktioniert genauso, wieint*
esvoid*
implizit konvertiert wird .int*
Code hinzugefügt .quelle
void *
, sondern zufloat *
und sindchar *
. Diese Darsteller sind nicht nur irrelevant, sie sind auch falsch.free(p)
scheitern? Würde es einen Compilerfehler geben?const
natürlich auch für Qualifikationszeiger.volatile
existiert seit C standardisiert wurde, wenn nicht länger. Es wurde nicht in C99 hinzugefügt.Alter Grund: 1. Bei Verwendung von
free((sometype*) ptr)
Code wird explizit angegeben, welcher Typ der Zeiger als Teil desfree()
Aufrufs betrachtet werden soll. Die explizite Besetzung ist nützlich, wenn siefree()
durch eine (Do-it-yourself) ersetzt wirdDIY_free()
.A
DIY_free()
war (ist) eine Möglichkeit, insbesondere im Debug-Modus, eine Laufzeitanalyse des freigegebenen Zeigers durchzuführen. Dies wird häufig mit aDIY_malloc()
kombiniert, um Sententials, globale Speicherauslastungszahlen usw. hinzuzufügen. Meine Gruppe hat diese Technik jahrelang verwendet, bevor modernere Tools erscheinen. Es war verpflichtet, dass der Gegenstand, der frei war, auf den Typ gegossen wurde, der ursprünglich zugewiesen wurde.Modern: Vermeiden
const
undvolatile
Warnen, wie von Manos Nikolaidis @ und @egur angesprochen . Dachte , ich würde die Auswirkungen der Anmerkung 3 - Qualifikation :const
,volatile
, undrestrict
.[bearbeiten]
char * restrict *rp2
Per @R .. Kommentar hinzugefügtquelle
restrict
ist nur aufgrund der Positionrp
kein Problem - es wirkt sich auf das Objekt aus, nicht auf den Typ, auf den verwiesen wird. Wenn Sie stattdessen hättenchar *restrict *rp
, wäre es wichtig.Hier ist eine andere alternative Hypothese.
Uns wird gesagt, dass das Programm vor C89 geschrieben wurde, was bedeutet, dass es keine Art von Nichtübereinstimmung mit dem Prototyp von umgehen kann
free
, weil es nicht nurconst
wedervoid *
vor noch vor C89 gab, noch gab es keine ein Funktionsprototyp vor C89.stdlib.h
selbst war eine Erfindung des Komitees. Wenn die System-Header sich die Mühe gemacht hätten, überhaupt zu deklarierenfree
, hätten sie es so gemacht:Der entscheidende Punkt hierbei ist, dass der Compiler aufgrund des Fehlens von Funktionsprototypen keine Überprüfung des Argumenttyps durchgeführt hat . Es wurden die Standardargument-Promotions angewendet (die gleichen, die immer noch für verschiedene Funktionsaufrufe gelten), und das war es. Die Verantwortung für die Argumentation auf jeder Call-Site, die den Erwartungen des Angerufenen entspricht, liegt vollständig beim Programmierer.
Dies bedeutet jedoch nicht, dass es notwendig war, das Argument
free
auf die meisten K & R-Compiler zu übertragen. Eine Funktion wiesollte korrekt kompiliert worden sein. Ich denke, wir haben hier ein Programm, das geschrieben wurde, um mit einem fehlerhaften Compiler für eine ungewöhnliche Umgebung fertig zu werden: zum Beispiel eine Umgebung, in
sizeof(float *) > sizeof(int)
der der Compiler dies nicht tun würde die entsprechende Aufrufkonvention für Zeiger verwenden wenn Sie sie nicht an der Stelle umwandeln des Anrufs.Ich kenne keine solche Umgebung, aber das bedeutet nicht, dass es keine gab. Die wahrscheinlichsten Kandidaten, die mir in den Sinn kommen, sind reduzierte "winzige C" -Compiler für 8- und 16-Bit-Mikros in den frühen 1980er Jahren. Ich wäre auch nicht überrascht zu erfahren, dass frühe Crays solche Probleme hatten.
quelle
free nimmt nur nicht konstante Zeiger als Parameter auf. Bei Konstantenzeigern ist daher eine explizite Umwandlung in einen Nicht-Konstantenzeiger erforderlich.
Konstantenzeiger in C können nicht freigegeben werden
quelle