Twitter iPhone pliant OnePlus 11 PS5 Disney+ Orange Livebox Windows 11

allocation dynamique

17 réponses
Avatar
Benoit Izac
Bonjour,

Soit le bout de code suivant :
-----------------------------------------------------------------------
#include <stdio.h>

#define SIZE 256

int main(void)
{
char *dirname = "/sys/class/power_supply";
char *type = "BAT";
int n = 1;
char *basename = "status";
char filename[SIZE];

if (snprintf(filename, SIZE, "%s/%s%d/%s", dirname, type, n,
basename)) {
/* on utilise filename */
} else {
/* on gere l'erreur */
}

return 0;
}
-----------------------------------------------------------------------

Je souhaiterai me passer de SIZE et donc allouer dynamiquement filename.

J'ai pensé à faire ceci :
-----------------------------------------------------------------------
char *filename;
/* size_of(n) renvoie le nombre de caractère(s) nécessaire(s) pour
représenter n en décimal */
size_t size = strlen(dirname) + 1 + strlen(type) + 1 + size_of(n) + 1 +
strlen(basename) + 1;
filename = malloc(size);
if (filename) {
if (snprintf(filename, size, "%s/%s%d/%s", dirname, type, n,
basename)) {
/* ... */
}
free(filename);
}
-----------------------------------------------------------------------

Est-ce la seule manière de procéder ?

NB: j'ai bien pensé à regarder comment asprintf (GNU_SOURCE) faisait
mais j'y comprend rien. ;)
--
Benoit Izac

7 réponses

1 2
Avatar
Alexandre BACQUART
Eric Levenez wrote:
Le 14/03/09 19:03, dans <49bbf156$0$3094$, « Alexandre
BACQUART » a écrit :

Il y a FILENAME_MAX dans <stdio.h>. C'est la taille maximum garantie par
l'implémentation pour les noms de fichiers (la norme va à peine plus
loin : s'il n'y a pratiquement aucune limite, c'est la taille
*recommandée* à allouer pour contenir les noms de fichiers).



Attention, FILENAME_MAX est la taille maximum d'un nom de fichier, alors que
là on veut allouer le chemin complet vers ce fichier. Là la norme C ne dit
rien vue que la notion de répertoire y est absente. Il y a bien PATH_MAX qui
est Posix mais il est parfois faux. Le mieux est donc de ne pas supposer la
taille maximale.



En effet, autant pour moi !

Dans ce cas, sauf si on est vraiment très serré niveau mémoire, le mieux
est certainement de faire soit-même un choix sur la taille maximum
plutôt que de se compliquer la vie à calculer ce que snprintf() nous
renverra.



--
Alex
Avatar
Alexandre BACQUART
Benoit Izac wrote:
Bonjour,

le 14/03/2009 à 19:03, Alexandre BACQUART a écrit dans le message
<49bbf156$0$3094$ :

Ensuite, si ton souhait est de stocker ces chemins de manière
compacte, le mieux est de copier cette chaîne (que tu vas libérer de
toutes façons) dans une autre, mais cette fois tu connais la taille
minimum à allouer : strlen(filename)+1 (ou mieux dans ton cas, le
retour de ton snprintf(...)+1).



J'ai juste donné l'exemple que j'avais en tête. Le but était d'avoir une
réponse générique qui me permette de connaître la taille exacte
à allouer pour stocker cette chaîne.



Ok, je viens de comprendre. Je croyais que le but était différent.

snprintf(NULL, 0, ...) remplit parfaitement ce rôle.



Oui.


--
Alex
Avatar
espie
In article <49bbf156$0$3094$,
Alexandre BACQUART wrote:
Il y a FILENAME_MAX dans <stdio.h>. C'est la taille maximum garantie par
l'implémentation pour les noms de fichiers (la norme va à peine plus
loin : s'il n'y a pratiquement aucune limite, c'est la taille
*recommandée* à allouer pour contenir les noms de fichiers).



<sarcasme>
En fait ca marche bien. Tu fais comme ca, et t'attends qu'un developpeur
de Hurd gueule que c'est trop limite, et t'envoie le patch qui va bien
pour lever la limite sur les longueurs de noms de fichiers.

</sarcasme>

En vrai, pathconf(3) est ton ami des que tu es sur un systeme POSIX, et
a defaut, FILENAME_MAX...
Avatar
Alexandre BACQUART
Marc Espie wrote:
In article <49bbf156$0$3094$,
Alexandre BACQUART wrote:
Il y a FILENAME_MAX dans <stdio.h>. C'est la taille maximum garantie par
l'implémentation pour les noms de fichiers (la norme va à peine plus
loin : s'il n'y a pratiquement aucune limite, c'est la taille
*recommandée* à allouer pour contenir les noms de fichiers).



<sarcasme>
En fait ca marche bien. Tu fais comme ca, et t'attends qu'un developpeur
de Hurd gueule que c'est trop limite, et t'envoie le patch qui va bien
pour lever la limite sur les longueurs de noms de fichiers.

</sarcasme>



En vrai, pathconf(3) est ton ami des que tu es sur un systeme POSIX, et
a defaut, FILENAME_MAX...



Encore que même à défaut... c'est encore mieux avec snprintf(). C'est
pratique, mais je trouve que ça manque d'élégance.


NB: tu n'aurais pas un problème de caractères accentués ou ça vient de moi ?


--
Alex
Avatar
Antoine Leca
Le 14/03/2009 14:19, Xavier Roche écrivit :
Eric Levenez a écrit :
Le plus simple est de demander à snprintf la taille requise avant de
faire un malloc et de refaire le snprintf dans le buffer alloué :



Il y a aussi une extension GNU (non POSIX) qui alloue ce qu'il faut
(asprintf)



Cette situation est temporaire :
http://open-std.org/jtc1/sc22/wg14/www/docs/n1337.pdf


Antoine
Avatar
Antoine Leca
Le 14/03/2009 14:35, Benoit Izac écrivit :
size_t size = snprintf(NULL, 0, "%s/%s%d/%s", dirname, type, n,
basename) + 1;



D'où ma question, comment faisait-on avant C99 (avec sprintf() donc) ?



Pour les %s, on utilisait des str[n]cpy, aujourd'hui surpassés par strlcpy.
Pour le %d, on utilise la solution que tu proposais initialement,
calculer la taille théorique maxi (en se servant du fait que Log10(2)
est très proche de 0,3) et sprintf.
Le tout baignant dans un bain de realloc().


Antoine
Avatar
Antoine Leca
Le 14/03/2009 18:03, Alexandre BACQUART écrivit :
NB: j'ai bien pensé à regarder comment asprintf (GNU_SOURCE) faisait
mais j'y comprend rien. ;)



Pas standard.



Pour le moment.
http://open-std.org/jtc1/sc22/wg14/www/docs/n1337.pdf


Antoine
1 2