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

lire des types different depuis un pointeur void*

6 réponses
Avatar
WebShaker
bonjour.


j'ai un pointeur de type void *
void *buffer;

comment je peux lire (en une seule instruction) une donnée 32bit et post
incrémenter le pointeur ?

pour le moment, je fais:
uint32_t totalsize = *(uint32_t *)buffer; vptr+=4;

j'aimerai bien faire ça en une seul instruction.
est-ce possible ?

merci
Etienne.

6 réponses

Avatar
Pascal J. Bourguignon
WebShaker writes:

j'ai un pointeur de type void *
void *buffer;

comment je peux lire (en une seule instruction) une donnée 32bit et
post incrémenter le pointeur ?

pour le moment, je fais:
uint32_t totalsize = *(uint32_t *)buffer; vptr+=4;

j'aimerai bien faire ça en une seul instruction.
est-ce possible ?



Oui. Utilise ',' au lieu de ';'.

uint32_t totalsize;
totalsize=(*(uint32_t*)buffer),(buffer+=sizeof(uint32_t));

--
__Pascal Bourguignon__ http://www.informatimago.com/
A bad day in () is better than a good day in {}.
Avatar
WebShaker
Le 24/07/2011 14:31, Pascal J. Bourguignon a écrit :
Oui. Utilise ',' au lieu de ';'.

uint32_t totalsize;
totalsize=(*(uint32_t*)buffer),(buffer+=sizeof(uint32_t));



Heu la c'est exactement la même chose.
ma question était plutôt:
est il possible de coller le ++ quelques part dans la premier instruction.

en gros ou mettre le ++ dans
uint32_t totalsize = *(uint32_t *)buffer;
pour incrémenter le pointeur de la taille de uint32_t ?

Etienne
Avatar
Pascal J. Bourguignon
WebShaker writes:

Le 24/07/2011 14:31, Pascal J. Bourguignon a écrit :
Oui. Utilise ',' au lieu de ';'.

uint32_t totalsize;
totalsize=(*(uint32_t*)buffer),(buffer+=sizeof(uint32_t));



Heu la c'est exactement la même chose.



Non, c'est trés différent. Il y a au moins deux bogues en moins, est
c'est exactement ce que tu demandais: une seule instruction.


ma question était plutôt:
est il possible de coller le ++ quelques part dans la premier instruction.



Il n'y a là qu'une sule instruction. Ta question est donc insensé.


en gros ou mettre le ++ dans
uint32_t totalsize = *(uint32_t *)buffer;
pour incrémenter le pointeur de la taille de uint32_t ?




Tu pourrais écrire:

uint32_t* p=buffer; /* ce n'est pas une instruction, mais une definition */
uint32_t totalsize=(*buffer++); /* ce n'est pas toujours as une instruction */

Total: zero instructions. Donc ça ne répond pas à ta question.


Tu pourrais écrire:

uint32_t* p;
uint32_t totalsize;
p=buffer,totalsize=(*buffer++); /* Une seule instruction */

mais tu ne l'aime pas.


Tu pourrais écrire:

uint32_t* p=buffer;
uint32_t totalsize;
totalsize=(*buffer++); /* Une seule instruction */

mais je ne vois pas l'intérêt.



--
__Pascal Bourguignon__ http://www.informatimago.com/
A bad day in () is better than a good day in {}.
Avatar
Pierre Maurette
WebShaker :
bonjour.


j'ai un pointeur de type void *
void *buffer;

comment je peux lire (en une seule instruction) une donnée 32bit et post
incrémenter le pointeur ?

pour le moment, je fais:
uint32_t totalsize = *(uint32_t *)buffer; vptr+=4;

j'aimerai bien faire ça en une seul instruction.
est-ce possible ?



Il me semble que c'est même classique, c'est par exemple ce qu'on fait
tout les jours quand on reçoit le résultat d'un malloc() qui est un
void*.

uint32_t* curseur = buffer; /* ou ... = malloc(...);*/

unuint32_t = *curseur++;
unautreuint32_t = *curseur++;

C'est juste de l'arithmétique des pointeurs.
Pensez également que s'il y a allocation quelque part, il vous faudra
conserver pour libération, d'une façon ou d'une autre, la valeur de
buffer ou la valeur initiale de curseur.

Ou alors je n'ai pas pigé la question ?

--
Pierre Maurette
Avatar
Alexandre Bacquart
On 07/24/2011 02:21 PM, WebShaker wrote:
bonjour.


j'ai un pointeur de type void *
void *buffer;

comment je peux lire (en une seule instruction) une donnée 32bit et post
incrémenter le pointeur ?



Déjà, on ne fait pas d'arithmétique sur void*, c'est hasardeux.

Par exemple, GCC considère l'arithmétique sur void* identique à celle de
char* (en émettant un warning). Je ne suis pas sûr que ce soit très sage
de sa part, mais d'autres t'enverront peut-être carrément balader.

pour le moment, je fais:
uint32_t totalsize = *(uint32_t *)buffer; vptr+=4;



Kesako vptr ? un char* ?

Que se passe-t-il si CHAR_BIT > 8 ? :) Mieux vaut utiliser
sizeof(uint32_t) plutôt que 4.

j'aimerai bien faire ça en une seul instruction.
est-ce possible ?



Pas sûr de bien comprendre ce que tu veux faire. Si ton intention est
d'optimiser, tu perds ton temps : un bon compilateur saura faire ce
qu'il faut pour transformer tes "2 instructions" en une seule, si
possible (et en l'occurrence, la plupart des microprocesseurs sont
capables de faire cette opération, et même souvent plus, en un cycle
maximum). De ce point de vue, "une seule instruction" ne signifie pas
grand chose en C.

Ce que tu demandes reviendrait à écrire :

uint32_t totalsize = *((uint32_t *) buffer)++;

Ce qui n'est pas possible puisqu'après le cast, il n'y a plus de lvalue.

Peut-être que ton intention est alors de faciliter l'écriture et la
lecture ? Tu peux t'en sortir avec des macros, mais leur définition
dépend de ce que tu veux vraiment faire... un peu plus d'infos
contextuelles peut-être ? En fait, ce qui semble relativement clair dans
le sujet est obscurci dans l'énoncé.


--
Alexandre
Avatar
espie
In article ,
Pascal J. Bourguignon wrote:
WebShaker writes:

j'ai un pointeur de type void *
void *buffer;

comment je peux lire (en une seule instruction) une donnée 32bit et
post incrémenter le pointeur ?

pour le moment, je fais:
uint32_t totalsize = *(uint32_t *)buffer; vptr+=4;

j'aimerai bien faire ça en une seul instruction.
est-ce possible ?



Oui. Utilise ',' au lieu de ';'.

uint32_t totalsize;
totalsize=(*(uint32_t*)buffer),(buffer+=sizeof(uint32_t));



BIIIP!!! faux !
On est bien dans fr.comp.lang.c ?

void *buffer;

buffer += sizeof(uint32_t);

n'est pas standard. Il n'y a PAS d'arithmetique de pointeur sur les void *.

Ceux-ci n'ont pas de taille. Il faut imperativement les caster en quelque
chose avant de pouvoir travailler avec.

gcc "permet" de faire cela pour des raisons de commodite, car c'est un des
trucs specifies dans la norme (avant C89, void* n'avait evidemment pas un
statut bien defini), mais il balance plein de warnings en mode pedantic.

On ne peut pas non plus juste faire
(char *)buffer += sizeof(uint32_t);
c'est encore plus incorrect (utilisation de cast comme une lvalue). Il faut
au minimum un truc genre:
buffer = (char *)buffer + sizeof(uint32_t);
qui lui est correct, meme si nettement plus long...

ce dont, au final, on se fout un peu, parce que c'est juste le code source,
et que le code machine correspondant sera exactement identique.

La difference etant qu'un code est portable et correct, et les autres non.

Pourquoi faire des cochonneries non portables quand du code conforme donne
exactement le meme resultat avec les memes performances ? ...