Je lis un livre ( Programmation avec des fils POSIX de Butenhof, 1997) qui utilise C, et je suis tombé sur la ligne suivante:
(void)free(data);
Ici, data
est juste un pointeur vers une structure allouée,
data = malloc(sizeof(my_struct_t));
Pourquoi le résultat free
est-il lancé void
?
D'après ma compréhension de C, cela ne semble pas logique pour deux raisons:
- La fonction gratuite revient déjà
void
- Le code n'utilise pas la valeur de retour (il n'est même pas affecté à une variable)
Le livre a été écrit en 1997. Est-ce une sorte d'héritage?
L'auteur mentionne que les exemples ont été exécutés sur Digital Unix 4.0d, mais je ne peux toujours pas imaginer une raison de lancer le résultat d'une fonction si vous n'utilisez pas ce résultat.
free()
comme une bizarrerie dans le livre que vous n'avez pas besoin d'émuler. Il y a longtemps, il était semi-pertinent, mais il n'est plus pertinent.Réponses:
Si nous parlons de la
free
fonction standard , son prototype estPar conséquent, le casting est complètement inutile.
Maintenant, quelques spéculations.
L'auteur a peut-être oublié d'inclure l'en-
stdlib.h
tête déclarant ce prototype, donc le compilateur en assume le type de retour commeint
. Maintenant, lors de l'analyse statique de ce code, le compilateur avertissait de la valeur de retour inutilisée de ce qu'il pense être une non-void
fonction. De tels avertissements sont généralement réduits au silence en ajoutant le casting àvoid
.la source
free
celui qu'il a réellement, avec pour résultat que l'appel a un comportement non défini (en supposant la sémantique C90, où l'appel d'une fonction non déclarée ne présente pas intrinsèquement UB dans tous les cas). En pratique, il est plausible que cela se traduise par une mauvaise conduite de bonne foi sur certains systèmes. La bonne solution consiste à fournir une déclaration correcte pour la fonction.Ce serait un héritage!
Avant qu'il n'y ait un standard C, la
free()
fonction aurait été (implicitement) de typeint
- car il n'y avait pas encore de type fiablevoid
pour qu'elle revienne. Aucune valeur n'a été renvoyée.Lorsque le code a été modifié pour la première fois pour fonctionner avec des compilateurs C standard, il ne comprenait probablement pas
<stdlib.h>
(car il n'existait pas avant la norme). L'ancien code écrivaitextern char *malloc();
(peut-être sansextern
) pour les fonctions d'allocation (de même pourcalloc()
etrealloc()
), et n'avait pas besoin de déclarerfree()
. Et le code convertirait ensuite la valeur de retour dans le type correct - car cela était nécessaire sur au moins certains systèmes (y compris celui sur lequel j'ai appris C).Quelque temps plus tard, la
(void)
distribution a été ajoutée pour indiquer au compilateur (ou, plus probablement,lint
) que "la valeur de retour defree()
est délibérément ignorée" pour éviter une plainte. Mais il aurait été préférable d'ajouter<stdlib.h>
et de laisser sa déclarationextern void free(void *vp);
direlint
au compilateur qu'il n'y avait aucune valeur à ignorer.JFTR: au milieu des années 80, l'ICL Perq était à l'origine sur une architecture orientée mots et l'
char *
adresse d'un emplacement mémoire était un nombre très différent du pointeur "else_else" vers le même emplacement. Il était crucial de déclarer enchar *malloc()
quelque sorte; il était crucial d'en convertir le résultat en n'importe quel autre type de pointeur. Le casting a en fait changé le nombre utilisé par le CPU. (Il y avait aussi beaucoup de joie lorsque la mémoire principale de nos systèmes a été mise à niveau de 1 Mio à 2 Mio - puisque le noyau utilisait environ 3/4 Mio, cela signifiait que les programmes utilisateur pouvaient utiliser 1 1/4 Mio avant la pagination, etc.)la source
free()
sur p. 177 qui revient implicitementint
.void
été ajouté à certains systèmes (Unix System III, peut-être) avant la publication de la norme, mais cela ne faisait pas partie de C lorsque K&R 1st Edn a été écrit (1978). Une fonction qui n'a pas retourné de valeur a été déclarée sans type de retour (ce qui signifie qu'elle a renvoyéint
), et tant que vous n'avez pas utilisé la valeur qui n'a pas été retournée, il n'y a pas eu de problème. La norme C90 devait traiter ce type de code comme valide - elle aurait échoué lamentablement comme une norme ne l'avait pas fait. Mais C99 a supprimé lesint
règles «implicite » et «déclaration de fonction implicite». Tout le code du monde n'a pas été rattrapé.(void)
casting pourprintf()
??Ce casting n'est pas nécessaire. Cela n'aurait probablement pas été le cas à l'époque, car C avait été normalisé sous la forme de C89.
Si cela avait été le cas, cela serait dû à une déclaration implicite . Cela signifiait généralement que la personne qui écrivait le code avait oublié
#include <stdlib.h>
et qu'un analyseur statique était utilisé. Ce n'est pas la meilleure solution de contournement et une bien meilleure idée aurait été de le faire à la#include <stdlib.h>
place. Voici quelques mots de C89 sur la déclaration implicite:Mais c'est étrange car ils ne convertissent pas le résultat de l'
malloc
un et de l' autremalloc
etfree
sont dans le même fichier d'en-tête.Il est également possible que ce soit juste une erreur ou un moyen de dire au lecteur qu'il
free
ne renvoie aucun résultat.la source
free
mais pas pourmalloc
.