3

LLNLからのpthreadチュートリアルを読んで、次のサンプルコードをヒットしました

/******************************************************************************
* FILE: hello.c
* DESCRIPTION:
*   A "hello world" Pthreads program.  Demonstrates thread creation and
*   termination.
* AUTHOR: Blaise Barney
* LAST REVISED: 08/09/11
******************************************************************************/
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#define NUM_THREADS 5

void *PrintHello(void *threadid)
{
   long tid;
   tid = (long)threadid;
   printf("Hello World! It's me, thread #%ld!\n", tid);
   pthread_exit(NULL);
}

int main(int argc, char *argv[])
{
   pthread_t threads[NUM_THREADS];
   int rc;
   long t;
   for(t=0;t<NUM_THREADS;t++){
     printf("In main: creating thread %ld\n", t);
     rc = pthread_create(&threads[t], NULL, PrintHello, (void *)t);
     if (rc){
       printf("ERROR; return code from pthread_create() is %d\n", rc);
       exit(-1);
       }
     }

   /* Last thing that main() should do */
   pthread_exit(NULL);
}

なぜlongキャストスルーされているのかがわかります(そうではvoid *なく、スレッドによって出力された数字へのポインターを渡すとt文字化けします)、私の質問は、これをコーシャと見なして常に機能する必要があるかどうかです。それとも、これはスレッド化の最も単純な例を機能させるための簡単なハックですか?これは標準のCのものですか?

4

2 に答える 2

4

いいえ、ポインタが long を保持するのに十分な幅であるという保証がないため、ISO C 標準に関して厳密にはコーシャではありません。

コーシャの解決策は、スレッドごとに 1 つの一意の long (配列内の 1 つなど) を使用するか、作成者スレッドと作成されたスレッドの間でスレッド間通信 (条件変数など) を使用して、long へのポインターを渡すことです。後者は、前者が次のスレッド作成のために変更を許可される前に、コピーを作成できます。

ただし、厳密にコーシャではないという事実は、特定の実装で機能しないという意味ではありません。void*の間のキャストを保証できlong、情報が失われない場合、おそらく問題なく動作します。

C11 から6.3.2.3 Pointers(ただし、C99 からほとんど変更されていません):

整数は、任意のポインター型に変換できます。前に指定された場合を除き、結果は実装定義であり、正しく配置されていない可能性があり、参照された型のエンティティを指していない可能性があり、トラップ表現である可能性があります。

任意のポインター型を整数型に変換できます。前に指定された場合を除き、結果は実装定義です。結果が整数型で表現できない場合、動作は未定義です。結果は、任意の整数型の値の範囲内にある必要はありません。

于 2012-09-05T05:24:20.473 に答える
0

これは 32 ビット システムでのみ正しいです。64 ビット システムの場合、long のサイズは 32 ビットですが、void* のサイズは 64 ビット長です。

于 2012-09-05T05:29:26.393 に答える