web-dev-qa-db-fra.com

Comment convertir un entier en pointeur vide?

En travaillant avec Threads in C, je suis confronté à l'avertissement

"warning: transtyper le pointeur à partir d'un entier de taille différente"

Le code est comme suit

#include<stdio.h>
#include<sys/types.h>
#include<stdlib.h>
#include<pthread.h>
void *print(void *id)
{
 int a=10;
 printf("My thread id is %ld\n",pthread_self());
 printf("Thread %d is executing\n",id);
 return (void *) 42;
}

int main()
{
 pthread_t th[5];
 int t;
 int i;
 int status;
 void *ret;
 for(i=0;i<5;i++)
 {
   status=pthread_create(&th[i],NULL,print,(void *)i); //Getting warning at this line
   if(status)
   {
    printf("Error creating threads\n");
    exit(0);
   }
   pthread_join(th[i],&ret);
   printf("--->%d\n",(int *)ret);
 }
 pthread_exit(NULL);
}

Quelqu'un peut-il expliquer comment passer un entier à une fonction qui reçoit (void *) en tant que paramètre?

21
Dinesh

C'est un excellent moyen de passer des entiers à de nouvelles pthreads, si c'est ce dont vous avez besoin. Vous avez juste besoin de supprimer l'avertissement, et cela le fera:

#include <stdint.h>

void *threadfunc(void *param)
{
    int id = (intptr_t) param;
    ...
}

int i, r;
r = pthread_create(&thread, NULL, threadfunc, (void *) (intptr_t) i);

Discussion

Cela peut heurter votre sensibilité, mais il s'agit de très court et il n'y a pas de conditions de concurrence (comme ce serait le cas si vous utilisiez &i). Cela ne sert à rien d’écrire quelques dizaines de lignes de code supplémentaire pour obtenir un ensemble de threads numérotés.

Courses de données

Voici une version bad avec une course de données:

#include <pthread.h>
#include <stdio.h>

#define N 10

void *thread_func(void *arg)
{
    int *ptr = arg;
    // Has *ptr changed by the time we get here?  Maybe!
    printf("Arg = %d\n", *ptr);
    return NULL;
}

int main()
{
    int i;
    pthread_t threads[N];
    for (i = 0; i < N; i++) {
        // NO NO NO NO this is bad!
        pthread_create(&threads[i], NULL, thread_func, &i);
    }
    for (i = 0; i < N; i++) {
        pthread_join(threads[i], NULL);
    }
    return 0;
}

Maintenant, que se passe-t-il lorsque je l'exécute avec le désinfectant pour filetage?

(Voir aussi comment il imprime "5" deux fois ...)

 ================= 
 AVERTISSEMENT: ThreadSanitizer: course de données (pid = 20494) 
 Lecture de taille 4 à 0x7ffc95a834ec par le thread T1: 
 # 0 thread_func /home/depp/test.c:9 (a.out + 0x000000000a8c) 
 # 1 <null> <null> (libtsan.so.0 + 0x000000023519) 

 Écriture précédente de taille 4 à 0x7ffc95a834ec par le thread principal: 
 # 0 main /home/depp/test.c:17 (a.out + 0x000000000b3a) 

 L'emplacement est une pile de filetage principal .

 Thread T1 (tid = 20496, en cours d'exécution) créé par le thread principal à: 
 # 0 pthread_create <null> (libtsan.so.0 + 0x0000000273d4) 
 # 1 principal /home/depp/test.c:18 (a.out + 0x000000000b1c) 

 Résumé: ThreadSanitizer: course de données /home/depp/test.c:9 thread_func 
 ==== =============... Arg = 1 
 Arg = 2 
 Arg = 3 
 Arg = 4 
 Arg = 5 
 Arg = 6 
 Arg = 7 
 Arg = 8 
 Arg = 9 
 Arg = 5 
 ThreadSanitizer: a signalé 1 avertissements 
35
Dietrich Epp

vous pouvez faire quelque chose comme ça:

#include <stdio.h>
#include <sys/types.h>
#include <stdlib.h>
#include <pthread.h>
struct th {
    pthread_t thread;
    int id;
    int ret;
};

void *print(void *id) {
    int a=10;
    struct th *self = (struct th *) id;
    printf("My thread id is %ld\n",pthread_self());
    printf("Thread %d is executing\n",self->id);
    self->ret = random();
    return;
}

int main(void) {
    struct th th[5];
    int t;
    int i;
    int status;
    void *ret;
    for(i=0;i<5;i++) {
        th[i].id = i;
        status=pthread_create(&th[i].thread,NULL,print,&th[i]); //Getting warning at this line
        if(status) {
            printf("Error creating threads\n");
            exit(0);
        }
    }
    for (i=0;i<5;i++) {
        pthread_join(th[i].thread,&ret);
        printf("%d--->%d\n",th[i].id,th[i].ret);

    }
    pthread_exit(NULL);
}

affichera:

My thread id is 4496162816
My thread id is 4497870848
My thread id is 4498944000
My thread id is 4498407424
Thread 0 is executing
Thread 1 is executing
My thread id is 4499480576
Thread 3 is executing
Thread 2 is executing
0--->1804289383
Thread 4 is executing
1--->846930886
2--->1714636915
3--->1681692777
4--->1957747793

passer un pointeur unique à chaque thread ne fera pas la course, et vous pouvez obtenir/sauvegarder n'importe quel type d'information dans la structure

0
jackdoe

vous pouvez passer la valeur int en tant que pointeur vide comme (void *)&n où n est un entier, et dans la fonction accepter le pointeur vide comme paramètre comme void foo(void *n);et enfin à l'intérieur de la fonction, convertir le pointeur vide en int, comme suit, int num = *(int *)n;. De cette façon, vous ne recevrez aucun avertissement.

0
Rahul