web-dev-qa-db-ja.com

整数をvoidポインターにキャストする方法は?

Cでスレッドを操作している間、私は警告に直面しています

「警告:異なるサイズの整数からポインターへのキャスト」

コードは次のとおりです

#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);
}

(void *)をパラメーターとして受け取る関数に整数を渡す方法を誰かが説明できますか?

21
Dinesh

これは、必要に応じて、整数を新しいpthreadに渡すための優れた方法です。警告を抑制する必要があるだけで、次のようになります。

#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);

討論

これはあなたの感性を害するかもしれませんが、それは非常に短く、競合状態がありません(&iを使用した場合のように)。番号付きのスレッドの束を取得するためだけに数十行の追加コードを書く意味はありません。

データ競合

これがbadデータ競合のバージョンです。

#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;
}

では、スレッドサニタイザーで実行するとどうなりますか?

(また、「5」が2回印刷される方法も確認してください...)

 ================== 
警告:ThreadSanitizer:データレース(pid = 20494)
サイズ4の0x7ffc95a834ecでの読み取りスレッドT1:
によって#0 thread_func /home/depp/test.c:9(a.out + 0x000000000a8c)
#1 <null> <null>(libtsan.so.0 + 0x000000023519 )
 
メインスレッドによる0x7ffc95a834ecでのサイズ4の以前の書き込み:
#0 main /home/depp/test.c:17(a.out + 0x000000000b3a)
 
場所はメインスレッドのスタックです。
 
メインスレッドによって作成されたスレッドT1(tid = 20496、実行中):
#0 pthread_create <null> (libtsan.so.0 + 0x0000000273d4)
#1 main /home/depp/test.c:18(a.out + 0x000000000b1c)
 
要約:ThreadSanitizer:データレース/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:1つの警告が報告されました
38
Dietrich Epp

あなたはこのようなことをすることができます:

#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);
}

出力されます:

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

各スレッドに一意のポインターを渡しても競合することはなく、th構造体であらゆる種類の情報を取得/保存できます

0
jackdoe

_(void *)&n_のようなvoidポインターとしてint値を渡すことができます。ここで、nは整数です。関数内では、void foo(void *n);のようなパラメーターとしてvoidポインターを受け入れ、最後に関数内でvoidポインターをint num = *(int *)n;。これにより、警告が表示されなくなります。

0
Rahul