74 votes

erreur: cast de 'void *' à 'int' perd de la précision

J'ai une fonction avec le prototype void* myFcn(void* arg) qui est utilisée comme point de départ pour un pthread. J'ai besoin de convertir l'argument en int pour un usage ultérieur:

 int x = (int)arg;
 

Le compilateur (GCC version 4.2.4) renvoie l'erreur:

 file.cpp:233: error: cast from 'void*' to 'int' loses precision
 

Quelle est la bonne façon de lancer ceci?

70voto

Ferruccio Points 51508

Vous pouvez le convertir en intptr_t . C'est un type int garanti d'être assez grand pour contenir un pointeur. Utilisez #include <cstdint> pour le définir.

34voto

onlooker Points 199

Encore une fois, toutes les réponses ci-dessus raté le point de mal. L'OP voulait convertir une valeur de type pointeur vers un int valeur, au lieu de cela, la plupart des réponses, d'une façon ou l'autre, essayé à tort de convertir le contenu d'arg points pour une valeur int. Et, la plupart de ces ne travaillent même sur gcc4.

La bonne réponse est, si l'on ne veut pas perdre la précision des données,

int x = *((int*)(&arg));

Cela fonctionne sur GCC4.

Le mieux est, si l'on peut, ne pas faire ce genre de casting, en revanche, si la même adresse mémoire partagée pour le pointeur de int (par exemple, pour l'enregistrement de RAM), l'utilisation de l'union, et assurez-vous que, si le mem adresse est considéré comme un int seulement si vous savez, c'était comme un int.

13voto

AndreyT Points 139512

Il n'y a pas de moyen approprié de le convertir en int dans le cas général. La bibliothèque standard C99 fournit intptr_t et uintptr_t types de fichiers, qui sont supposés être utilisés chaque fois que le besoin de procéder à une telle conversion est nécessaire. Si votre bibliothèque standard (même si ce n'est pas C99) fournit ces types, utilisez-les. Sinon, vérifiez la taille du pointeur sur votre plate-forme, définissez vous-même ces typedef et utilisez-les.

13voto

Joshua D. Boyd Points 1876

Au lieu de:

 int x = (int)arg;
 

utilisation:

 int x = (long)arg;
 

Sur la plupart des plates-formes, les pointeurs et les longs ont la même taille, mais les ints et les pointeurs ne sont souvent pas de la même taille sur les plates-formes 64 bits. Si vous convertissez ( void* ) en ( long ) aucune précision n’est perdue, puis en affectant le ( long ) à un ( int ), il tronque correctement le nombre à adapter.

8voto

Loki Astari Points 116129

Le moulage d'un pointeur de type void* et à l'arrière est valable de reinterpret_cast<>. Donc, vous pourriez faire ceci:

pthread_create(&thread, NULL, myFcn, new int(5)); // implicit cast to void* from int*

Puis dans myFcn:

void* myFcn(void* arg)
{
    int*  data = reinterpret_cast<int*>(arg);
    int   x    = *data;
    delete data;

Remarque: Comme sbi souligne cela nécessiterait un changement sur l'OP appel à la création du thread.

Ce que j'essaie de mettre l'accent sur la conversion de int en pointeur et le dos encore une fois peut-être frough avec des problèmes lorsque vous vous déplacez d'une plateforme à une autre. MAIS la conversion d'un pointeur de type void* et le dos encore une fois est bien pris en charge (partout).

Donc par conséquent, il peut être moins enclins à faire des erreurs pour générer un pointeur dynamcially et l'utiliser. Se souvenir de supprimer le pointeur après utilisation, de sorte que nous n'avons pas de fuite.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X