Je travaille sur une ancienne base de code et à peu près chaque invocation de free () utilise un cast sur son argument. Par exemple,
free((float *)velocity);
free((float *)acceleration);
free((char *)label);
où chaque pointeur est du type correspondant (et correspondant). Je ne vois aucun intérêt à faire cela. C'est un code très ancien, donc je me demande si c'est un truc K&R. Si tel est le cas, je souhaite en fait prendre en charge les anciens compilateurs qui peuvent avoir nécessité cela, donc je ne veux pas les supprimer.
Y a-t-il une raison technique d'utiliser ces moulages? Je ne vois même pas beaucoup de raison pragmatique de les utiliser. À quoi bon se rappeler le type de données juste avant de le libérer?
EDIT: Cette question n'est pas une duplication de l'autre question. L'autre question est un cas particulier de cette question, qui, je pense, est évidente si les électeurs proches liraient toutes les réponses.
Colophon: Je coche la "réponse const" parce que c'est une vraie raison pour laquelle cela pourrait devoir être fait; cependant, la réponse à ce sujet étant une coutume pré-ANSI C (du moins chez certains programmeurs) semble être la raison pour laquelle il a été utilisé dans mon cas. Beaucoup de bons points par beaucoup de gens ici. Merci pour vos contributions.
void*
de C pré-standard, mais seulementchar*
. Donc, si vos découvertes archéologiques révèlent un code convertissant le paramètre en free (), je pense qu'il doit être soit de cette période, soit écrit par une créature de cette époque. Cependant, je ne trouve aucune source à ce sujet, alors je m'abstiendrai de répondre.Réponses:
Le cast peut être nécessaire pour résoudre les avertissements du compilateur si les pointeurs le sont
const
. Voici un exemple de code qui provoque un avertissement sans lancer l'argument de free:Et le compilateur (gcc 4.8.3) dit:
Si vous utilisez
free((float*) velocity);
le compilateur cesse de vous plaindre.la source
float*
avant de libérer. J'ai essayéfree((void *)velocity);
avec gcc 4.8.3. Bien sûr, cela ne fonctionnerait pas avec un ancien compilateurconst char *p
comme argument et libère alors il, la bonne chose à faire est de ne pas jeterp
àchar*
avant d' appeler gratuitement. Il ne s'agit pas de le déclarer comme prenantconst char *p
en premier lieu, car il se modifie*p
et doit être déclaré en conséquence. (Et s'il prend un pointeur const au lieu d'un pointeur vers const,int *const p
vous n'avez pas besoin de lancer car il est en fait légal et fonctionne donc très bien sans le cast.)Pré-standard C n'avait pas
void*
mais seulementchar*
, vous deviez donc convertir tous les paramètres passés. Si vous rencontrez un ancien code C, vous pourriez donc trouver de tels moulages.Question similaire avec références .
Lorsque la première norme C a été publiée, les prototypes pour malloc et free sont passés de l'avoir
char*
àvoid*
ce qu'ils ont encore aujourd'hui.Et bien sûr, dans la norme C, de tels moulages sont superflus et nuisent à la lisibilité.
la source
free
dans le même type qu'il est déjà?free
ne savent pas comment les transtypages du paramètre fonctionnent en C standard (vous n'avez pas besoin de lancer). Je n'ai pas lu la 1ère édition, donc je ne peux pas dire s'ils étaient également confus à l'époque pré-standard des années 80.void*
, mais il n'avait pas non plus de prototypes de fonction, donc le cast de l'argument defree
était toujours inutile même dans K&R (en supposant que tous les types de pointeurs de données utilisaient la même représentation).char *
. Quel sens cela aurait-il dans les vieux compilateurs sansvoid
? Que permettraient de tels moulages?Voici un exemple où la gratuité échouerait sans un casting:
En C, vous pouvez obtenir un avertissement (vous en avez un dans VS2012). En C ++, vous obtiendrez une erreur.
Hormis les rares cas, le casting ne fait que gonfler le code ...
Edit: J'ai casté pour
void*
neint*
pas démontrer l'échec. Il fonctionnera de la même manière queint*
sera converti envoid*
implicitement.int*
Code ajouté .la source
void *
, mais versfloat *
etchar *
. Ces moulages ne sont pas simplement étrangers, ils sont faux.free(p)
échouerait? Cela donnerait-il une erreur de compilation?const
pointeurs de qualification, évidemment.volatile
existe depuis que C a été standardisé, sinon plus. Il n'a pas été ajouté dans C99.Ancienne raison: 1. En utilisant
free((sometype*) ptr)
, le code est explicite sur le type que le pointeur doit être considéré comme faisant partie de l'free()
appel. Le cast explicite est utile lorsqu'ilfree()
est remplacé par un (do-it-yourself)DIY_free()
.A
DIY_free()
était (est) une certaine manière, en particulier en mode débogage, pour effectuer une analyse d' exécution du pointeur étant libéré. Ceci est souvent associé à unDIY_malloc()
pour ajouter des identifiants, des comptes globaux d'utilisation de la mémoire, etc. Mon groupe a utilisé cette technique pendant des années avant que des outils plus modernes n'apparaissent. Il obligeait à ce que l'élément en cours de libération ait été lancé dans le type qui lui avait été attribué à l'origine.Moderne: éviter
const
etvolatile
avertissements tels que traités par Manos Nikolaidis @ et @egur . Je pensais noterais les effets des 3 qualificatifs :const
,volatile
etrestrict
.[modifier] Ajouté
char * restrict *rp2
par @R .. commentairela source
restrict
n'est pas un problème en raison de l'endroit où il est placé - cela affecte l'objet etrp
non le type pointé. Si vous l'aviez à la placechar *restrict *rp
, alors ce serait important.Voici une autre hypothèse alternative.
On nous dit que le programme a été écrit avant C89, ce qui signifie qu'il ne peut pas contourner une sorte de non-concordance avec le prototype de
free
, car non seulement il n'y avait rien de tel queconst
nivoid *
avant C89, mais il n'existait pas de un prototype de fonction avant C89.stdlib.h
elle-même était une invention du comité. Si les en-têtes système avaient pris la peine de déclarerfree
du tout, ils l'auraient fait comme ceci:Maintenant, le point clé ici est que l'absence de prototypes de fonction signifiait que le compilateur n'a pas vérifié le type d'argument . Il a appliqué les promotions d'argument par défaut (les mêmes qui s'appliquent toujours aux appels de fonction variadiques) et c'était tout. La responsabilité de faire correspondre les arguments à chaque site d'appel avec les attentes de l'appelé incombait entièrement au programmeur.
Cependant, cela ne signifie toujours pas qu'il était nécessaire de lancer l'argument
free
sur la plupart des compilateurs K&R. Une fonction commeaurait dû être compilé correctement. Je pense donc que nous avons ici un programme écrit pour faire face à un compilateur bogué pour un environnement inhabituel: par exemple, un environnement où
sizeof(float *) > sizeof(int)
et le compilateur ne le ferait pas la convention d'appel appropriée pour les pointeurs à moins que vous ne les castiez au point de l'appel.Je ne suis pas au courant d'un tel environnement, mais cela ne veut pas dire qu'il n'y en avait pas. Les candidats les plus probables qui me viennent à l'esprit sont les compilateurs «minuscules C» réduits pour les micros 8 et 16 bits au début des années 80. Je ne serais pas non plus surpris d'apprendre que les premiers Crays avaient des problèmes comme celui-ci.
la source
free n'accepte que les pointeurs non const comme paramètre. Ainsi, dans le cas des pointeurs const, un cast explicite en un pointeur non const est requis.
Impossible de libérer les pointeurs const en C
la source