Dans le code suivant, deux fonctions (fill et fill_2) sont proposées pour remplir la variable list[], déclarée ligne 30.
De ce que j’ai compris, la fonction fill est préférable parce que l’autre fonction induit une fuite de mémoire irrécupérable.
Ce que je ne comprends pas, c’est pourquoi la fonction fill fonctionne.
La valeur contenue dans temp n’est-elle pas automatiquement effacée au retour de la fonction ?
#include<stdio.h>#include<stdlib.h>typedefstructAB
{int a, b;
} AB;
voidfill(AB* list){
AB temp;
temp.a = 47;
temp.b = 23;
list[0] = temp;
}
voidfill_2(AB* list){
AB* temp = malloc(sizeof(AB));
temp->a = 47;
temp->b = 23;
list[0] = *temp;
}
intmain(void){
AB list[1];
fill_2(list); // à tester aussi avec : fill(list);printf("list.a : %d\nlist.b : %d\n", list[0].a, list[0].b);
return EXIT_SUCCESS;
}
Lorsque tu fais l’opération en ligne 16, le contenu de la structure temp est copié dans la cellule list[0]. Donc oui, après l’exécution de la fonction, la mémoire stack est dépilée et temp est "libérée" (avec des gros guillemets), mais c’est pas grave puisqu’on a copié son contenu là où c’était nécessaire.
La valeur contenue dans temp n’est-elle pas automatiquement effacée au retour de la fonction ?
Si. Mais avant la destruction de temp, tu en fais une copie dans list[0].
Qu’il vaudrait mieux écrire *list par ailleurs (bien que ce soit équivalent), pour éviter toute confusion sur le fait que tu manipules qu’un seul élément et non pas un tableau.
Rajout: grillé, mais c’est pas grave, je poste quand même
C’est un peu compliqué. Pourquoi NULL ? Mais oui, c’est vrai.
Bon comme la définition de NULL est un peu complexe, c’est pas évident de répondre, mais avec d’autres paragraphes de la norme on conclut que dans tous les cas où la sizeof T <= sizeof(void*) alors oui !E est équivalent à E==0 (ou E==NULL).
Bon, j’ai cherché un contre exemple rapidement. J’ai trouvé ça si ton compilateur supporte __int128 (c’était la première fois que j’utilisais ce type d’ailleurs).
Mmm… Je ne vois pas le rapport entre ton exemple et la question « est-ce que !variable est équivalent à variable == NULL ». La macroconstante NULL correspond soit à 0 soit à (void *)0.
Autrement dit, au vu de la définition de l’opérateur ! (citée précédemment), on a un cas où c’est strictement équivalent (NULL est définie comme valant zéro) et un cas un peu différent où NULL vaut (void *)0. Toutefois, c’est sans compter les conversions implicites induites par l’opérateur ==.
En bref, si NULL vaut zéro, alors elle sera convertie vers le type du second opérande, si en revanche elle vaut (void *)0, c’est le second opérande qui sera converti vers le type void *.
char *p = 0;
/*
* 0 == p => (char *)0 == p
*
* OU
*
* (void *)0 == p => (void *)0 == (void *)p
*/
Toutefois, le résultat sera le même.
En bref, est-ce que !pointeur est strictement équivalent à pointeur == NULL ? Si NULL vaut zéro, oui, si NULL vaut (void *)0, non. Néanmoins, le résultat sera identique.
Voilà
Tu es arrivé à la même conclusion que moi mais en détaillant tout le raisonnement.
Le truc, c’est que l’OP a parlé d’expression !variable et variable == NULL sans pour autant préciser que variable serait un pointeur.
En supposant que NULL vaille (void*)0 et que variable ne soit pas un pointeur, alors il est possible que !variable ne soit pas équivalent à variable == NULL.
Dans tous les autres cas, variable == NULL équivaut à !variable.
Ah en fait du coup les deux derniers messages ont embrouillés un peu ma compréhension de ce que je pensais avoir compris.
Pour simplifier, peut-on affirmer que si variable est soit un pointeur (char*, void*, int*…) , soit une variable classique (int, char, short…), alors !variable est strictement équivalent à variable == NULL ? (Oui, d’après ce que j’ai compris.)
Si chez toi, est NULL ne s’affiche pas, c’est que NULL vaut 0, ce qui est compatible avec la norme.
Tu peux simuler le fait que NULL soit égale à (void*)0 en ajoutant ceci :
@ache si NULL est défini avec (void*) 0, ta comparaison est de toute façon un undefined behavior (comparaison entier qui n’est pas une constante 0 avec pointeur).
Connectez-vous pour pouvoir poster un message.
Connexion
Pas encore membre ?
Créez un compte en une minute pour profiter pleinement de toutes les fonctionnalités de Zeste de Savoir. Ici, tout est gratuit et sans publicité.
Créer un compte