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

Addition de pointeur et de valeur numérique

9 réponses
Avatar
Oupss
Bonjour à tous,

Comment puis-je addition un pointeur de structure et une valeur
numérique sans que le compilateur sorte un warning.
J'ai par exemple:

struct toto {
char *string
} toto;

// Creation d'un vecteur de pointeur de taille n
struct toto *t = malloc(sizeof(toto *) * n);


Et je désire d’accéder à un élément du vecteur qui se trouve a la
position i :

struct toto *element = t + sizeof(toto*) * i;

Merci à tous.

9 réponses

Avatar
Pascal J. Bourguignon
Oupss writes:

Bonjour à tous,

Comment puis-je addition un pointeur de structure et une valeur
numérique sans que le compilateur sorte un warning.
J'ai par exemple:

struct toto {
char *string
} toto;

// Creation d'un vecteur de pointeur de taille n
struct toto *t = malloc(sizeof(toto *) * n);

Et je désire d’accéder à un élément du vecteur qui se trouve a la
position i :

struct toto *element = t + sizeof(toto*) * i;



struct toto *element = &(t[i]);

--
__Pascal Bourguignon__ http://www.informatimago.com/
A bad day in () is better than a good day in {}.
Avatar
Samuel DEVULDER
Le 07/05/2012 18:52, Oupss a écrit :

// Creation d'un vecteur de pointeur de taille n
struct toto *t = malloc(sizeof(toto *) * n);


^^^^^^^^^^^^^
pourquoi toto* ici? Si tu veux n "toto" consécutifs,
(hypothèse 1) tu dois réserver n*sizeof(toto) et pas
sizeof(toto*). Tu peux aussi virer le struct dans
struct toto vu que tu t'es défini le type "toto" tout
court:

toto *t = malloc(sizeof(toto) * n);

A noter que dans ce cas ca n'est pas un vecteur de
pointeur que tu veux, mais un vecteur de "toto".
Si tu veux vraiment avoir un vecteur de pointeurs sur
des elements "toto" épars (hypothèse 2), alors tu dois
écrire:

toto* *t = malloc(sizeof(toto*) * n);

Dans tous les cas, si tu fais attention tu verras que le
nombre d'étoiles "*" dans le type de t est toujours un de
plus que le nombre d'étoiles utilisé dans le sizeof. C'est
logique d'un coté on a des élements, donc une indirection
de plus par rapport au pointeur.

Et je désire d’accéder à un élément du vecteur qui se trouve a la
position i :

struct toto *element = t + sizeof(toto*) * i;


^^^^^^^^^^^^^
Non, l'arithmétique de pointeur fait cela automatiquement
pour toi: il faut utiliser t + i qui pointe exactement sur
l'adresse de t[i].

toto *element = t + i; // ou &t[i]

Cela marche aussi dans l'hypothèse ou t est un toto** (ton
vecteur de pointeurs de l'hyptohèse 2), t + i pointera sur le
i-eme toto*. Attention C'est un pointeur non initialisé.. il
ne faudra pas oublier d'allouer le toto correspondant et le
placer en t[i]. C'est tellement compliqué que je pense que ce
n'est probablement pas vraiment ce que tu veux faire et que
tu as en réalité en tête l'hypothèse 1.

sam.
Avatar
Oupss
Je vous remercie beaucoup. Cela fonctionne parfaitement.

sam> Je suis dans l'hypothèse 2. Le plus gros problème c'est la
désallocation de la mémoire. (Je suis entrains de concevoir un mini
compilateur avec un Arbre syntaxique abstrait), j'ai plain de pointeur
qui sont utiliser, ils se baladent dans différente variable. Je ne sais
jamais quand je peu les désallouter.

On 05/07/2012 07:06 PM, Samuel DEVULDER wrote:
Le 07/05/2012 18:52, Oupss a écrit :

// Creation d'un vecteur de pointeur de taille n
struct toto *t = malloc(sizeof(toto *) * n);


^^^^^^^^^^^^^
pourquoi toto* ici? Si tu veux n "toto" consécutifs,
(hypothèse 1) tu dois réserver n*sizeof(toto) et pas
sizeof(toto*). Tu peux aussi virer le struct dans
struct toto vu que tu t'es défini le type "toto" tout
court:

toto *t = malloc(sizeof(toto) * n);

A noter que dans ce cas ca n'est pas un vecteur de
pointeur que tu veux, mais un vecteur de "toto".
Si tu veux vraiment avoir un vecteur de pointeurs sur
des elements "toto" épars (hypothèse 2), alors tu dois
écrire:

toto* *t = malloc(sizeof(toto*) * n);

Dans tous les cas, si tu fais attention tu verras que le
nombre d'étoiles "*" dans le type de t est toujours un de
plus que le nombre d'étoiles utilisé dans le sizeof. C'est
logique d'un coté on a des élements, donc une indirection
de plus par rapport au pointeur.

Et je désire d’accéder à un élément du vecteur qui se trouve a la
position i :

struct toto *element = t + sizeof(toto*) * i;


^^^^^^^^^^^^^
Non, l'arithmétique de pointeur fait cela automatiquement
pour toi: il faut utiliser t + i qui pointe exactement sur
l'adresse de t[i].

toto *element = t + i; // ou &t[i]

Cela marche aussi dans l'hypothèse ou t est un toto** (ton
vecteur de pointeurs de l'hyptohèse 2), t + i pointera sur le
i-eme toto*. Attention C'est un pointeur non initialisé.. il
ne faudra pas oublier d'allouer le toto correspondant et le
placer en t[i]. C'est tellement compliqué que je pense que ce
n'est probablement pas vraiment ce que tu veux faire et que
tu as en réalité en tête l'hypothèse 1.

sam.
Avatar
Pascal J. Bourguignon
Oupss writes:

Je vous remercie beaucoup. Cela fonctionne parfaitement.

sam> Je suis dans l'hypothèse 2. Le plus gros problème c'est la
désallocation de la mémoire. (Je suis entrains de concevoir un mini
compilateur avec un Arbre syntaxique abstrait), j'ai plain de pointeur
qui sont utiliser, ils se baladent dans différente variable. Je ne sais
jamais quand je peu les désallouter.



http://www.hpl.hp.com/personal/Hans_Boehm/gc/

--
__Pascal Bourguignon__ http://www.informatimago.com/
A bad day in () is better than a good day in {}.
Avatar
conan28
Le lundi 7 mai 2012 19:06:29 UTC+2, Samuel DEVULDER a écrit :
A noter que dans ce cas ca n'est pas un vecteur de
pointeur que tu veux, mais un vecteur de "toto".
Si tu veux vraiment avoir un vecteur de pointeurs sur
des elements "toto" épars (hypothèse 2), alors tu dois
écrire:

toto* *t = malloc(sizeof(toto*) * n);



Je sais que le sujet se fait un peu vieux, mais j'ose rappeler que ce genre de déclarations sont très trompeuses. En effet, si on fait toto* *t, * p; p sera de type toto* et non de type toto**, comme on pourrait l'imaginer . Du coup, on considère que p et t, c'est la même salade, alors que pas du tout...
À bon entendeur ;)
Avatar
espie
In article ,
wrote:
Le lundi 7 mai 2012 19:06:29 UTC+2, Samuel DEVULDER a écrit :
A noter que dans ce cas ca n'est pas un vecteur de
pointeur que tu veux, mais un vecteur de "toto".
Si tu veux vraiment avoir un vecteur de pointeurs sur
des elements "toto" épars (hypothèse 2), alors tu dois
écrire:

toto* *t = malloc(sizeof(toto*) * n);



Je sais que le sujet se fait un peu vieux, mais j'ose rappeler que ce
genre de déclarations sont très trompeuses. En effet, si on fait toto*
*t, *p; p sera de type toto* et non de type toto**, comme on pourrait
l'imaginer. Du coup, on considère que p et t, c'est la même salade,
alors que pas du tout...
À bon entendeur ;)



Ouais, enfin bon, la, c'est quand meme de l'idiome a peu pres standard,
meme si Samuel melange un peu des pratiques C++ (coller l'* au type)
avec le reste.

Genre, n'importe quel programmeur C non debutant est cense reconnaitre un
T *p = malloc(sizeof(T) * n);
pour ce qu'il est, et ce quel que soit le type T....
Avatar
JKB
Le Wed, 25 Jul 2012 09:01:39 +0000 (UTC),
Marc Espie écrivait :
In article ,
wrote:
Le lundi 7 mai 2012 19:06:29 UTC+2, Samuel DEVULDER a écrit :
A noter que dans ce cas ca n'est pas un vecteur de
pointeur que tu veux, mais un vecteur de "toto".
Si tu veux vraiment avoir un vecteur de pointeurs sur
des elements "toto" épars (hypothèse 2), alors tu dois
écrire:

toto* *t = malloc(sizeof(toto*) * n);



Je sais que le sujet se fait un peu vieux, mais j'ose rappeler que ce
genre de déclarations sont très trompeuses. En effet, si on fait toto*
*t, *p; p sera de type toto* et non de type toto**, comme on pourrait
l'imaginer. Du coup, on considère que p et t, c'est la même salade,
alors que pas du tout...
À bon entendeur ;)



Ouais, enfin bon, la, c'est quand meme de l'idiome a peu pres standard,
meme si Samuel melange un peu des pratiques C++ (coller l'* au type)
avec le reste.

Genre, n'importe quel programmeur C non debutant est cense reconnaitre un
T *p = malloc(sizeof(T) * n);
pour ce qu'il est, et ce quel que soit le type T....



Ouaips, enfin, moi, je programme en Fortran dans n'importe quel
langage. Une instruction par ligne et une seule. Ça évite ce genre
de chose ;-)

JKB

--
Si votre demande me parvient sur carte perforée, je titiouaillerai très
volontiers une réponse...
=> http://grincheux.de-charybde-en-scylla.fr
Avatar
Samuel DEVULDER
Le 25/07/2012 11:01, Marc Espie a écrit :

Ouais, enfin bon, la, c'est quand meme de l'idiome a peu pres standard,
meme si Samuel melange un peu des pratiques C++ (coller l'* au type)
avec le reste.



et si c'était une simple t ypo en plus ?

sam ;-)
Avatar
Samuel DEVULDER
Le 25/07/2012 10:26, a écrit :
Le lundi 7 mai 2012 19:06:29 UTC+2, Samuel DEVULDER a écrit :
A noter que dans ce cas ca n'est pas un vecteur de
pointeur que tu veux, mais un vecteur de"toto".
Si tu veux vraiment avoir un vecteur de pointeurs sur
des elements"toto" épars (hypothèse 2), alors tu dois
écrire:

toto* *t = malloc(sizeof(toto*) * n);



Je sais que le sujet se fait un peu vieux,



Oula oui, j'avais oublié. :o

mais j'ose rappeler que ce genre de déclarations sont très trompeuses.



Le compilo va certainement détecter un pb de typage à un moment
ou un autre. Donc le risque est léger si on ne (cast) pas à tord
et à travers.

Sinon on peut aussi forcer les gens à n'utiliser qu'un seul niveau
d'étoile, et un max de typedef pour clairement exprimer sur quoi
on veut pointer.

typedef toto *tableau_de_toto;
tableau_de_toto *t = malloc(sizeof(tableau_de_toto) * n);

Après tout, donner un nom symbolique "tableau_de_toto" à un type
presque anonyme "toto*" alors qu'on utilise souvent comme une
entité propre du programme doit aider à la compréhension du code.

En tout cas utiliser un nom symbolique pour les joyeusetés style
pointeur sur une fonction retournant un tableau de pointeur sur
fonctions prenant en entrée un tableau 4x3 d'entiers et sortant un
double, moi je ne dis surtout pas non.

sam.