void* myFcn(void* arg)
pthreadの開始点として使用されるプロトタイプを使用した関数があります。後で使用するために、引数をintに変換する必要があります。
int x = (int)arg;
コンパイラ(GCCバージョン4.2.4)は次のエラーを返します。
file.cpp:233: error: cast from 'void*' to 'int' loses precision
これをキャストする適切な方法は何ですか?
void* myFcn(void* arg)
pthreadの開始点として使用されるプロトタイプを使用した関数があります。後で使用するために、引数をintに変換する必要があります。
int x = (int)arg;
コンパイラ(GCCバージョン4.2.4)は次のエラーを返します。
file.cpp:233: error: cast from 'void*' to 'int' loses precision
これをキャストする適切な方法は何ですか?
型にキャストできますintptr_t
。これint
は、ポインターを格納するのに十分な大きさであることが保証されている型です。を使用#include <cstdint>
して定義します。
繰り返しますが、上記のすべての回答は要点を大幅に逃していました。OPはポインター値をint値に変換したかったのですが、代わりに、ほとんどの回答が何らかの方法でargポイントの内容を誤ってint値に変換しようとしました。そして、これらのほとんどは gcc4 でも動作しません。
正解は、データの精度が失われることを気にしないのであれば、
int x = *((int*)(&arg));
これは GCC4 で動作します。
最善の方法は、可能であればそのようなキャストを行わないことです。代わりに、ポインターと int で同じメモリアドレスを共有する必要がある場合 (RAM の保存など)、union を使用し、mem アドレスが処理されるかどうかを確認してください。最後に int として設定されたことがわかっている場合にのみ、int として。
それ以外の:
int x = (int)arg;
使用する:
int x = (long)arg;
ほとんどのプラットフォームではポインターと long は同じサイズですが、64 ビット プラットフォームでは int とポインターが同じサイズではないことがよくあります。void*
( ) を ( ) に変換しても精度が失われることはありません。( ) を ( ) にlong
代入すると、数値が適切に切り捨てられます。long
int
一般的にこれをキャストする適切な方法はありませんint
。C99 標準ライブラリにはintptr_t
、型定義と型定義が用意uintptr_t
されています。これらは、そのようなキャストを実行する必要が生じたときにいつでも使用されることになっています。標準ライブラリ (C99 でなくても) がこれらの型を提供している場合は、それらを使用してください。そうでない場合は、プラットフォームのポインター サイズを確認し、これらの typedef を自分で定義して使用します。
void* へのポインターのキャストとその逆は、reinterpret_cast<> の有効な使用法です。だからあなたはこれを行うことができます:
pthread_create(&thread, NULL, myFcn, new int(5)); // implicit cast to void* from int*
次に myFcn で:
void* myFcn(void* arg)
{
int* data = reinterpret_cast<int*>(arg);
int x = *data;
delete data;
注: sbi が指摘しているように、スレッドを作成するには OP 呼び出しを変更する必要があります。
私が強調しようとしているのは、int からポインターへの変換、およびその逆の変換は、プラットフォームからプラットフォームに移動するときに問題が発生する可能性があるということです。ただし、ポインターを void* に変換してから戻すことは、(どこでも) 十分にサポートされています。
したがって、結果として、ポインターを動的に生成して使用する方がエラーが発生しにくい可能性があります。漏れないように、使用後にポインターを削除することを忘れないでください。
キャストを使用する代わりに、にlong
キャストする必要がありますsize_t
。
int val= (int)((size_t)arg);
私もこの問題に直面しています。
ids[i] = (int) arg; // error occur here => I change this to below.
ids[i] = (uintptr_t) arg;
その後、コンパイルを続行できます。多分あなたもこれを試すことができます。
適切な方法は、別の にキャストすることpointer type
です。void*
aから an への変換はint
移植性のない方法であり、機能する場合と機能しない場合があります。返されたアドレスを保持する必要がある場合は、そのまま保持してvoid*
ください。
最も安全な方法:
static_cast<int>(reinterpret_cast<long>(void * your_variable));
long
任意のマシン上の Linux でポインター サイズを保証します。Windows も 64 ビットでのみ 32 ビット長です。したがって、 64 ビットの Windowslong long
ではなくに変更する必要があります。long
したがって、データを切り捨てる準備ができている場合は、typeにキャストしてからreinterpret_cast
安全に にキャストします。long
static_cast
long
int
このようにスレッド作成関数を呼び出すと
pthread_create(&thread, NULL, myFcn, reinterpret_cast<void*>(5));
の内部にvoid*
到達すると、そこに入れられmyFcn
た値が得られます。int
だから、あなたはこのようにキャストバックできることを知っています
int myData = reinterpret_cast<int>(arg);
コンパイラは、整数と組み合わせてのみ渡すmyFcn
ことを知りません。pthread_create
編集:
Martin が指摘したように、これはsizeof(void*)>=sizeof(int)
. これが成り立たないプラットフォームにコードが移植される可能性がある場合、これは機能しません。
//new_fd is a int
pthread_create(&threads[threads_in_use] , NULL, accept_request, (void*)((long)new_fd));
//inside the method I then have
int client;
client = (long)new_fd;
お役に立てれば
int を a として渡さないで、 aをvoid*
に渡しint*
てくださいint
。これにより、 を にキャストしvoid*
、int*
参照解除されたポインターを にコピーできますint
。
int x = *static_cast<int*>(arg);
あなたが望むかもしれないのは
int x = reinterpret_cast<int>(arg);
void *
これにより、 をとして再解釈できますint
。
関数ポインターは void* (およびその他の非関数ポインター) と互換性がありません
これは、64 ビットのポインターを 32 ビットの整数に変換しているため、情報が失われるためです。
代わりに64ビット整数を使用できますが、通常は正しいプロトタイプで関数を使用し、関数タイプをキャストします。
void thread_func(int arg){
...
}
そして私はこのようなスレッドを作成します:
pthread_create(&tid, NULL, (void*(*)(void*))thread_func, (void*)arg);