Je d=E9bute avec le C depuis quelques mois =E0 mon rhytme. J'arrive au
chapitre de l'allocation dynamique. J'ai abord=E9 les tableaux uni et
multidimensionnels, les pointeurs, les fonctions.
En fait, je comprends l'utilit=E9 de malloc dans le sens ou la
r=E9servation de la m=E9moire pour un tableau peut se faire en cours
d'ex=E9cution...
Pour la saisie de texte, je voudrais savoir s'il serait possible de
saisir une cha=EEne de caract=E8re variable avec fgets ? Je pense beaucoup
=E0 utiliser realloc.
Par exemple : je r=E9serve de la m=E9moire pour un pointeur vers une
adresse de type caract=E8re, pour 1 ou 2 caract=E8res et =E0 je demande =E0
l'utilisateur de saisir du texte. A chaque saisie, je r=E9serve la place
pour un caract=E8re suppl=E9mentaire en m=E9moire avec realloc, c'est
faisable? Bizarement, je ne trouve aucun code qui correspond =E0 ce que
je recherche sur le net.
Ca ressemble =E0 peu pr=E8s, mais =E7a ne marche pas :
http://www.cppfrance.com/forum/sujet-RECUERATION-CHAINE-CARACTERE-TAILLE-VA=
RIABLE-STDIN_1405662.aspx
Autre question sans lien avec la premi=E8re :
est-ce que =E9crire char* chaine =3D 0 et char *chaine =3D 0 revient =E0 la
m=EAme chose?
/* lecture */ while (fgets(une_ligne, MAX_LINE, stdin)) { nombre_de_lignes++;
/* allocation pour une ligne en plus */ toutes_les_lignes = realloc(toutes_les_lignes, nombre_de_lignes * sizeof *toutes_les_lignes); if (!toutes_les_lignes) exit(1);
/* allocation pour stocker la ligne */ toutes_les_lignes[nombre_de_lignes - 1] malloc(strlen(une_ligne) + 1);
/* lecture */
while (fgets(une_ligne, MAX_LINE, stdin)) {
nombre_de_lignes++;
/* allocation pour une ligne en plus */
toutes_les_lignes = realloc(toutes_les_lignes,
nombre_de_lignes *
sizeof *toutes_les_lignes);
if (!toutes_les_lignes)
exit(1);
/* allocation pour stocker la ligne */
toutes_les_lignes[nombre_de_lignes - 1] malloc(strlen(une_ligne) + 1);
/* lecture */ while (fgets(une_ligne, MAX_LINE, stdin)) { nombre_de_lignes++;
/* allocation pour une ligne en plus */ toutes_les_lignes = realloc(toutes_les_lignes, nombre_de_lignes * sizeof *toutes_les_lignes); if (!toutes_les_lignes) exit(1);
/* allocation pour stocker la ligne */ toutes_les_lignes[nombre_de_lignes - 1] malloc(strlen(une_ligne) + 1);
/* affichage */ for (i = 0; i < nombre_de_lignes; i++) printf("%s", toutes_les_lignes[i]);
return 0; }
-- Benoit Izac
Antoine Leca
heron écrivit :
Dans le document de Xavier Jeannin, il dit (chapitre gestion dynamique : classe d'allocation : )
• statique : les données occupent un emplacement défini lors de la compilation. • automatique : les données sont créées dynamiquement au fur et à mesure de l'exécution du pgrm, dans la pile (stack) . • dynamique : les données sont créées ou détruites à l'initiative du programmeur. Elle sont créées dans le tas (heap).
Oui.
d'après mes connaissances :
- déclaration statique d'un tableau d'entier:
int Tableau[50] ;
Non.
Une déclaration statique, c'est normalement : static int Tableau[50] ;
*SAUF QUE* il y a des formes simplifiées, et d'autre part le mot-clé static signifie AUSSI « pas-extern », ce qui introduit de possibles confusions.
À l'intérieur d'une fonction, il ne peut pas y avoir de doute, static signifie statique (il n'est pas possible d'avoir une liaison externe pour une définition d'objet).
À l'extérieur d'une fonction, en portée globale, static signifie aussi «pas-extern» (liaison interne), donc si c'est ce que tu veux c'est bon tel quel ; si tu veux que l'objet soit visible depuis d'autres modules, il faut enlever le static, et dans ce cas-là l'allocation reste statique
- déclaration automatique (je ne suis pas très sûre) :
int Tab[50] ; int *pTab = Tab ; char *pTxt[50] ;
Oui, mais uniquement à l'intérieur d'une fonction : l'allocation automatique n'a pas de sens pour une variable globale.
La déclaration « char *pTxt[50] » déclare un tableau de 50 pointeurs (vers des chaînes).
est-ce que c'est équivalent à :
char Txt[50]; char *pTxt = Txt ;
Pas du tout. La première déclaration, celle de Txt, déclare UNE chaîne de 49 caractères au maximum (plus le ' ' final); la seconde, celle de pTxt, déclare UN pointeur vers chaîne ou caractère (contrairement aux 50 ci-dessus), et initialise ce pointeur au début de l'objet Txt.
L'auteur dit de qui est dynamique que ça se trouve dans le heap ou tas. Je pensais que tout ce qui était dynamique, malloc, realloc était toujours dans le stack ou pile.
Bin non.
Enfin, j'affirme sans être certain que les pointeurs se situent toujours sur la pile (stack) car plus rapides lors de l'exécution.
Absolument pas, cela n'a rien à voir. De fait, sur une machine actuelle et avec un compilateur normal, le temps d'accès aux objets locaux automatiques sur la pile ou au tas est exactement le même ; et le compilateur est capable de repérer les objets entiers ou pointeurs souvent utilisés (qu'ils soient statiques ou sur la pile ou sur le tas) et les mets en registre tout seul (et c'est le fait d'être en registre qui est effectivement plus rapide).
De toute manière, l'allocation ne concerne QUE la réservation d'espace pour l'objet, et est indépendante de l'utilisation qui est faite ultérieurement de l'objet.
En fait, on peut lire plus loin dans le document que realloc modifie la taille d'une zone déjà allouée. Je peux en conclure que :
Mauvaise conclusion. NULL correspond à l'absence d'objet. malloc(0) correspond en théorie à un objet (inutilisable) de 0 octets. Le fait que ce soit inutilisable a conduit plusieurs implémentations à remplacer le résultat inutilisable par NULL, dans le but d'empêcher ensuite l'utilisation illégale du pointeur ; mais il est d'autres implémentations qui possèdent le concept d'objet alloué vide, et dans ces cas-là {m,c,re}alloc(0) renvoie bien un objet valide.
Antoine
heron écrivit :
Dans le document de Xavier Jeannin, il dit (chapitre gestion
dynamique : classe d'allocation : )
• statique : les données occupent un emplacement défini lors de la
compilation.
• automatique : les données sont créées dynamiquement au fur et à
mesure de l'exécution du pgrm, dans la pile (stack) .
• dynamique : les données sont créées ou détruites à l'initiative du
programmeur. Elle sont créées dans le tas (heap).
Oui.
d'après mes connaissances :
- déclaration statique d'un tableau d'entier:
int Tableau[50] ;
Non.
Une déclaration statique, c'est normalement :
static int Tableau[50] ;
*SAUF QUE* il y a des formes simplifiées, et d'autre part le mot-clé
static signifie AUSSI « pas-extern », ce qui introduit de possibles
confusions.
À l'intérieur d'une fonction, il ne peut pas y avoir de doute, static
signifie statique (il n'est pas possible d'avoir une liaison externe
pour une définition d'objet).
À l'extérieur d'une fonction, en portée globale, static signifie aussi
«pas-extern» (liaison interne), donc si c'est ce que tu veux c'est bon
tel quel ; si tu veux que l'objet soit visible depuis d'autres modules,
il faut enlever le static, et dans ce cas-là l'allocation reste statique
- déclaration automatique (je ne suis pas très sûre) :
int Tab[50] ;
int *pTab = Tab ;
char *pTxt[50] ;
Oui, mais uniquement à l'intérieur d'une fonction : l'allocation
automatique n'a pas de sens pour une variable globale.
La déclaration « char *pTxt[50] » déclare un tableau de 50 pointeurs
(vers des chaînes).
est-ce que c'est équivalent à :
char Txt[50];
char *pTxt = Txt ;
Pas du tout.
La première déclaration, celle de Txt, déclare UNE chaîne de 49
caractères au maximum (plus le ' ' final); la seconde, celle de pTxt,
déclare UN pointeur vers chaîne ou caractère (contrairement aux 50
ci-dessus), et initialise ce pointeur au début de l'objet Txt.
L'auteur dit de qui est dynamique que ça se trouve dans le heap ou
tas. Je pensais que tout ce qui était dynamique, malloc, realloc était
toujours dans le stack ou pile.
Bin non.
Enfin, j'affirme sans être certain que les pointeurs se situent
toujours sur la pile (stack) car plus rapides lors de l'exécution.
Absolument pas, cela n'a rien à voir. De fait, sur une machine actuelle
et avec un compilateur normal, le temps d'accès aux objets locaux
automatiques sur la pile ou au tas est exactement le même ; et le
compilateur est capable de repérer les objets entiers ou pointeurs
souvent utilisés (qu'ils soient statiques ou sur la pile ou sur le tas)
et les mets en registre tout seul (et c'est le fait d'être en registre
qui est effectivement plus rapide).
De toute manière, l'allocation ne concerne QUE la réservation d'espace
pour l'objet, et est indépendante de l'utilisation qui est faite
ultérieurement de l'objet.
En fait, on peut lire plus loin dans le document que realloc modifie
la taille d'une zone déjà allouée. Je peux en conclure que :
Mauvaise conclusion.
NULL correspond à l'absence d'objet.
malloc(0) correspond en théorie à un objet (inutilisable) de 0 octets.
Le fait que ce soit inutilisable a conduit plusieurs implémentations à
remplacer le résultat inutilisable par NULL, dans le but d'empêcher
ensuite l'utilisation illégale du pointeur ; mais il est d'autres
implémentations qui possèdent le concept d'objet alloué vide, et dans
ces cas-là {m,c,re}alloc(0) renvoie bien un objet valide.
Dans le document de Xavier Jeannin, il dit (chapitre gestion dynamique : classe d'allocation : )
• statique : les données occupent un emplacement défini lors de la compilation. • automatique : les données sont créées dynamiquement au fur et à mesure de l'exécution du pgrm, dans la pile (stack) . • dynamique : les données sont créées ou détruites à l'initiative du programmeur. Elle sont créées dans le tas (heap).
Oui.
d'après mes connaissances :
- déclaration statique d'un tableau d'entier:
int Tableau[50] ;
Non.
Une déclaration statique, c'est normalement : static int Tableau[50] ;
*SAUF QUE* il y a des formes simplifiées, et d'autre part le mot-clé static signifie AUSSI « pas-extern », ce qui introduit de possibles confusions.
À l'intérieur d'une fonction, il ne peut pas y avoir de doute, static signifie statique (il n'est pas possible d'avoir une liaison externe pour une définition d'objet).
À l'extérieur d'une fonction, en portée globale, static signifie aussi «pas-extern» (liaison interne), donc si c'est ce que tu veux c'est bon tel quel ; si tu veux que l'objet soit visible depuis d'autres modules, il faut enlever le static, et dans ce cas-là l'allocation reste statique
- déclaration automatique (je ne suis pas très sûre) :
int Tab[50] ; int *pTab = Tab ; char *pTxt[50] ;
Oui, mais uniquement à l'intérieur d'une fonction : l'allocation automatique n'a pas de sens pour une variable globale.
La déclaration « char *pTxt[50] » déclare un tableau de 50 pointeurs (vers des chaînes).
est-ce que c'est équivalent à :
char Txt[50]; char *pTxt = Txt ;
Pas du tout. La première déclaration, celle de Txt, déclare UNE chaîne de 49 caractères au maximum (plus le ' ' final); la seconde, celle de pTxt, déclare UN pointeur vers chaîne ou caractère (contrairement aux 50 ci-dessus), et initialise ce pointeur au début de l'objet Txt.
L'auteur dit de qui est dynamique que ça se trouve dans le heap ou tas. Je pensais que tout ce qui était dynamique, malloc, realloc était toujours dans le stack ou pile.
Bin non.
Enfin, j'affirme sans être certain que les pointeurs se situent toujours sur la pile (stack) car plus rapides lors de l'exécution.
Absolument pas, cela n'a rien à voir. De fait, sur une machine actuelle et avec un compilateur normal, le temps d'accès aux objets locaux automatiques sur la pile ou au tas est exactement le même ; et le compilateur est capable de repérer les objets entiers ou pointeurs souvent utilisés (qu'ils soient statiques ou sur la pile ou sur le tas) et les mets en registre tout seul (et c'est le fait d'être en registre qui est effectivement plus rapide).
De toute manière, l'allocation ne concerne QUE la réservation d'espace pour l'objet, et est indépendante de l'utilisation qui est faite ultérieurement de l'objet.
En fait, on peut lire plus loin dans le document que realloc modifie la taille d'une zone déjà allouée. Je peux en conclure que :
Mauvaise conclusion. NULL correspond à l'absence d'objet. malloc(0) correspond en théorie à un objet (inutilisable) de 0 octets. Le fait que ce soit inutilisable a conduit plusieurs implémentations à remplacer le résultat inutilisable par NULL, dans le but d'empêcher ensuite l'utilisation illégale du pointeur ; mais il est d'autres implémentations qui possèdent le concept d'objet alloué vide, et dans ces cas-là {m,c,re}alloc(0) renvoie bien un objet valide.
Antoine
Antoine Leca
heron écrivit :
char *Txt[50] ; /* réservation d'un tableau de 50 lignes ou 50 chaînes? */
Non : réservation (sans initialisation) d'un tableau de 50 pointeurs ; utilisation normale : pour stocker un index (une table des matières) ; l'espace pour les chaînes indicées n'est PAS réservé.
char LongeurLigne[100] ; /* longueur d'une ligne */ ... for ( i = 0 ; i < 50 ; i++ ) { fgets(Txt, 50, stdin) ;
Non : Txt contient des pointeurs, pas des caractères.
Txt[i] = (char*) malloc(strlen(LongueurLigne)+1)
strlen(LongueurLigne) n'a de sens QUE si LongueurLigne a été préalablement remplie avec une chaîne (dont on s'est assuré qu'elle était bien terminée par ' ', ne PAS utiliser strncpy() à cet effet)
Sinon oui, c'est bien la manière normale d'initialiser un index.
Le gain de l'allocation dynamique d'un tableau de 50 lignes pour une longueur maximale de 100 caractères par ligne serait d'économiser de l'espace mémoire sur la longeur d'une ligne au lieu de déclarer : char Txt[50][100] ;
Oui.
Par contre l'inconvénient d'après moi est qu'on doit avoir une idée du nombre de ligne sans quoi on ne peux pas modifier facilement *Txt
Hum, pas vraiment. En fait dans un programme classique de gestion d'un tas de lignes de texte, tu as deux inconnues : - la longueur (maximum) des lignes ; - le nombre de lignes.
Dans la méthode : char Txt[50][100] ; tu fixes les deux inconnues (49 et 100) : avantage, il n'y a plus besoin de pointeurs, d'allocation dynamique etc. ; inconvénient, c'est moins souple, le jour où une des deux limites est franchie il faut recompiler le programme.
Dans la méthode : char *Txt[50] tu fixes la seconde inconnues (50 lignes), mais tu laisses la possibilité de gérer des lignes arbitrairement longues, dans la limite de la mémoire disponible ; l'entrée des lignes de taille arbitraire n'est pas résolue, il faut programmer cela (normalement avec des fgets et des realloc, cf. le début de ce fil).
Symétriquement, tu peux décider d'avoir des lignes de longueur limitée mais en nombre illimité : un exemple peut être de lire des cartes perforées. La déclaration clé sera #define TAILLE_CARTE 80 /*...*/ char (*Txt)[TAILLE_CARTE+1]; Il faudra faire un malloc() au début du programme pour une valeur « normale » du nombre de cartes ; s'il y a plus de cartes à lire, il faudra utiliser realloc() pour agrandir l'index. Par contre, la lecture de chaque carte reste facile, avec un simple if( !fgets(Txt[i], TAILLE_CARTE+1, flux_lecteur_cartes) ) abandon("erreur de lecture"); Évidemment, le jour où le lecteur de cartes est mis de côté et remplacé par autre chose, il faudra revoir ce programme...
Et si tu veux la totale, où aucune inconnue n'est figée, Benoît en a donné le détail.
Personnellement je n'aime pas faire l'hypothèse que realloc(NULL, se comporte comme malloc() : je sais bien que la plupart des implémentations sont OK, mais je trouve cela dangereux car on ne voit pas clairement la logique du programme : on redimensionne la chaîne, mais où se trouve le dimensionnement initial ?
Cela étant, il s'agit de style, ce n'est pas aussi important.
Antoine
heron écrivit :
char *Txt[50] ; /* réservation d'un tableau de 50 lignes ou 50
chaînes? */
Non : réservation (sans initialisation) d'un tableau de 50 pointeurs ;
utilisation normale : pour stocker un index (une table des matières) ;
l'espace pour les chaînes indicées n'est PAS réservé.
char LongeurLigne[100] ; /* longueur d'une ligne */
...
for ( i = 0 ; i < 50 ; i++ ) {
fgets(Txt, 50, stdin) ;
Non : Txt contient des pointeurs, pas des caractères.
Txt[i] = (char*) malloc(strlen(LongueurLigne)+1)
strlen(LongueurLigne) n'a de sens QUE si LongueurLigne a été
préalablement remplie avec une chaîne (dont on s'est assuré qu'elle
était bien terminée par ' ', ne PAS utiliser strncpy() à cet effet)
Sinon oui, c'est bien la manière normale d'initialiser un index.
Le gain de l'allocation dynamique d'un tableau de 50 lignes pour une
longueur maximale de 100 caractères par ligne serait d'économiser de
l'espace mémoire sur la longeur d'une ligne au lieu de déclarer :
char Txt[50][100] ;
Oui.
Par contre l'inconvénient d'après moi est qu'on doit avoir une idée du
nombre de ligne sans quoi on ne peux pas modifier facilement *Txt
Hum, pas vraiment. En fait dans un programme classique de gestion d'un
tas de lignes de texte, tu as deux inconnues :
- la longueur (maximum) des lignes ;
- le nombre de lignes.
Dans la méthode
: char Txt[50][100] ;
tu fixes les deux inconnues (49 et 100) : avantage, il n'y a plus besoin
de pointeurs, d'allocation dynamique etc. ; inconvénient, c'est moins
souple, le jour où une des deux limites est franchie il faut recompiler
le programme.
Dans la méthode
: char *Txt[50]
tu fixes la seconde inconnues (50 lignes), mais tu laisses la
possibilité de gérer des lignes arbitrairement longues, dans la limite
de la mémoire disponible ; l'entrée des lignes de taille arbitraire
n'est pas résolue, il faut programmer cela (normalement avec des fgets
et des realloc, cf. le début de ce fil).
Symétriquement, tu peux décider d'avoir des lignes de longueur limitée
mais en nombre illimité : un exemple peut être de lire des cartes
perforées. La déclaration clé sera
#define TAILLE_CARTE 80
/*...*/
char (*Txt)[TAILLE_CARTE+1];
Il faudra faire un malloc() au début du programme pour une valeur
« normale » du nombre de cartes ; s'il y a plus de cartes à lire, il
faudra utiliser realloc() pour agrandir l'index. Par contre, la lecture
de chaque carte reste facile, avec un simple
if( !fgets(Txt[i], TAILLE_CARTE+1, flux_lecteur_cartes) )
abandon("erreur de lecture");
Évidemment, le jour où le lecteur de cartes est mis de côté et remplacé
par autre chose, il faudra revoir ce programme...
Et si tu veux la totale, où aucune inconnue n'est figée, Benoît en a
donné le détail.
Personnellement je n'aime pas faire l'hypothèse que realloc(NULL, se
comporte comme malloc() : je sais bien que la plupart des
implémentations sont OK, mais je trouve cela dangereux car on ne voit
pas clairement la logique du programme : on redimensionne la chaîne,
mais où se trouve le dimensionnement initial ?
Cela étant, il s'agit de style, ce n'est pas aussi important.
char *Txt[50] ; /* réservation d'un tableau de 50 lignes ou 50 chaînes? */
Non : réservation (sans initialisation) d'un tableau de 50 pointeurs ; utilisation normale : pour stocker un index (une table des matières) ; l'espace pour les chaînes indicées n'est PAS réservé.
char LongeurLigne[100] ; /* longueur d'une ligne */ ... for ( i = 0 ; i < 50 ; i++ ) { fgets(Txt, 50, stdin) ;
Non : Txt contient des pointeurs, pas des caractères.
Txt[i] = (char*) malloc(strlen(LongueurLigne)+1)
strlen(LongueurLigne) n'a de sens QUE si LongueurLigne a été préalablement remplie avec une chaîne (dont on s'est assuré qu'elle était bien terminée par ' ', ne PAS utiliser strncpy() à cet effet)
Sinon oui, c'est bien la manière normale d'initialiser un index.
Le gain de l'allocation dynamique d'un tableau de 50 lignes pour une longueur maximale de 100 caractères par ligne serait d'économiser de l'espace mémoire sur la longeur d'une ligne au lieu de déclarer : char Txt[50][100] ;
Oui.
Par contre l'inconvénient d'après moi est qu'on doit avoir une idée du nombre de ligne sans quoi on ne peux pas modifier facilement *Txt
Hum, pas vraiment. En fait dans un programme classique de gestion d'un tas de lignes de texte, tu as deux inconnues : - la longueur (maximum) des lignes ; - le nombre de lignes.
Dans la méthode : char Txt[50][100] ; tu fixes les deux inconnues (49 et 100) : avantage, il n'y a plus besoin de pointeurs, d'allocation dynamique etc. ; inconvénient, c'est moins souple, le jour où une des deux limites est franchie il faut recompiler le programme.
Dans la méthode : char *Txt[50] tu fixes la seconde inconnues (50 lignes), mais tu laisses la possibilité de gérer des lignes arbitrairement longues, dans la limite de la mémoire disponible ; l'entrée des lignes de taille arbitraire n'est pas résolue, il faut programmer cela (normalement avec des fgets et des realloc, cf. le début de ce fil).
Symétriquement, tu peux décider d'avoir des lignes de longueur limitée mais en nombre illimité : un exemple peut être de lire des cartes perforées. La déclaration clé sera #define TAILLE_CARTE 80 /*...*/ char (*Txt)[TAILLE_CARTE+1]; Il faudra faire un malloc() au début du programme pour une valeur « normale » du nombre de cartes ; s'il y a plus de cartes à lire, il faudra utiliser realloc() pour agrandir l'index. Par contre, la lecture de chaque carte reste facile, avec un simple if( !fgets(Txt[i], TAILLE_CARTE+1, flux_lecteur_cartes) ) abandon("erreur de lecture"); Évidemment, le jour où le lecteur de cartes est mis de côté et remplacé par autre chose, il faudra revoir ce programme...
Et si tu veux la totale, où aucune inconnue n'est figée, Benoît en a donné le détail.
Personnellement je n'aime pas faire l'hypothèse que realloc(NULL, se comporte comme malloc() : je sais bien que la plupart des implémentations sont OK, mais je trouve cela dangereux car on ne voit pas clairement la logique du programme : on redimensionne la chaîne, mais où se trouve le dimensionnement initial ?
Cela étant, il s'agit de style, ce n'est pas aussi important.
Antoine
candide
-ed- a écrit :
Pour ça, il faudrait être certain que le comportement de malloc(0) soit bien défini par le C, ce dont je ne suis pas sûr.
C'est écrit dans la Norme, depuis ... 20 ans.
-ed- a écrit :
Pour ça, il faudrait être certain que le comportement de malloc(0)
soit bien défini par le C, ce dont je ne suis pas sûr.
Pour ça, il faudrait être certain que le comportement de malloc(0) soit bien défini par le C, ce dont je ne suis pas sûr.
C'est écrit dans la Norme, depuis ... 20 ans.
Pour malloc(0) ? relis attentivement...
candide
Marc Espie a écrit :
Pour malloc(0) ? relis attentivement...
Si, si. Ci-dessous le texte verbatim de la Norme C90 (extrait du livre de Plauger, "The Standard C Library") :
7.10.3 Memory management functions
The order and contiguity of storage allocated by successive calls to the calloc, malloc, and realloc functions is unspecified. (...) If the size of the space requested is zero, the behavior is implementation defined; the value returned shall be either a null pointer or a unique pointer.
La formulation de C99 est un peu plus précise que le "unique pointer".
Marc Espie a écrit :
Pour malloc(0) ? relis attentivement...
Si, si. Ci-dessous le texte verbatim de la Norme C90 (extrait du livre
de Plauger, "The Standard C Library") :
7.10.3 Memory management functions
The order and contiguity of storage allocated by successive calls to the
calloc, malloc, and realloc functions is unspecified.
(...)
If the size of the space requested is zero, the behavior is
implementation defined; the value returned shall be either a null
pointer or a unique pointer.
La formulation de C99 est un peu plus précise que le "unique pointer".
Si, si. Ci-dessous le texte verbatim de la Norme C90 (extrait du livre de Plauger, "The Standard C Library") :
7.10.3 Memory management functions
The order and contiguity of storage allocated by successive calls to the calloc, malloc, and realloc functions is unspecified. (...) If the size of the space requested is zero, the behavior is implementation defined; the value returned shall be either a null pointer or a unique pointer.
La formulation de C99 est un peu plus précise que le "unique pointer".
Jean-Marc Bourguet
candide writes:
Marc Espie a écrit :
> Pour malloc(0) ? relis attentivement...
Si, si. Ci-dessous le texte verbatim de la Norme C90 (extrait du livre de Plauger, "The Standard C Library") :
Marc le sait. C'est ta reponse qui laissait croire que la norme imposait l'equivalence entre
ptr = NULL;
et
ptr = malloc(0);
A+
-- Jean-Marc FAQ de fclc: http://www.levenez.com/lang/c/faq Site de usenet-fr: http://www.usenet-fr.news.eu.org
candide <candide@free.invalid> writes:
Marc Espie a écrit :
> Pour malloc(0) ? relis attentivement...
Si, si. Ci-dessous le texte verbatim de la Norme C90 (extrait du livre de
Plauger, "The Standard C Library") :
Marc le sait. C'est ta reponse qui laissait croire que la norme imposait
l'equivalence entre
ptr = NULL;
et
ptr = malloc(0);
A+
--
Jean-Marc
FAQ de fclc: http://www.levenez.com/lang/c/faq
Site de usenet-fr: http://www.usenet-fr.news.eu.org