76

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

これをキャストする適切な方法は何ですか?

4

18 に答える 18

71

型にキャストできますintptr_t。これintは、ポインターを格納するのに十分な大きさであることが保証されている型です。を使用#include <cstdint>して定義します。

于 2009-10-28T22:13:40.370 に答える
35

繰り返しますが、上記のすべての回答は要点を大幅に逃していました。OPはポインター値をint値に変換したかったのですが、代わりに、ほとんどの回答が何らかの方法でargポイントの内容を誤ってint値に変換しようとしました。そして、これらのほとんどは gcc4 でも動作しません。

正解は、データの精度が失われることを気にしないのであれば、

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

これは GCC4 で動作します。

最善の方法は、可能であればそのようなキャストを行わないことです。代わりに、ポインターと int で同じメモリアドレスを共有する必要がある場合 (RAM の保存など)、union を使用し、mem アドレスが処理されるかどうかを確認してください。最後に int として設定されたことがわかっている場合にのみ、int として。

于 2011-08-26T13:37:25.300 に答える
14

それ以外の:

int x = (int)arg;

使用する:

int x = (long)arg;

ほとんどのプラットフォームではポインターと long は同じサイズですが、64 ビット プラットフォームでは int とポインターが同じサイズではないことがよくあります。void*( ) を ( ) に変換しても精度が失われることはありません。( ) を ( ) にlong代入すると、数値が適切に切り捨てられます。longint

于 2009-10-28T22:09:13.143 に答える
13

一般的にこれをキャストする適切な方法はありませんint。C99 標準ライブラリにはintptr_t、型定義と型定義が用意uintptr_tされています。これらは、そのようなキャストを実行する必要が生じたときにいつでも使用されることになっています。標準ライブラリ (C99 でなくても) がこれらの型を提供している場合は、それらを使用してください。そうでない場合は、プラットフォームのポインター サイズを確認し、これらの typedef を自分で定義して使用します。

于 2009-10-28T22:38:36.190 に答える
8

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* に変換してから戻すことは、(どこでも) 十分にサポートされています。

したがって、結果として、ポインターを動的に生成して使用する方がエラーが発生しにくい可能性があります。漏れないように、使用後にポインターを削除することを忘れないでください。

于 2009-10-28T22:28:09.597 に答える
7

キャストを使用する代わりに、にlongキャストする必要がありますsize_t

int val= (int)((size_t)arg);
于 2013-09-04T11:04:29.893 に答える
5

私もこの問題に直面しています。

ids[i] = (int) arg; // error occur here => I change this to below.

ids[i] = (uintptr_t) arg;

その後、コンパイルを続行できます。多分あなたもこれを試すことができます。

于 2014-04-03T06:45:09.260 に答える
3

適切な方法は、別の にキャストすることpointer typeです。void*aから an への変換はint移植性のない方法であり、機能する場合と機能しない場合があります。返されたアドレスを保持する必要がある場合は、そのまま保持してvoid*ください。

于 2009-10-28T22:06:03.530 に答える
2

最も安全な方法:

static_cast<int>(reinterpret_cast<long>(void * your_variable));

long任意のマシン上の Linux でポインター サイズを保証します。Windows も 64 ビットでのみ 32 ビット長です。したがって、 64 ビットの Windowslong longではなくに変更する必要があります。longしたがって、データを切り捨てる準備ができている場合は、typeにキャストしてからreinterpret_cast安全に にキャストします。longstatic_castlongint

于 2011-04-07T10:21:16.723 に答える
1

このようにスレッド作成関数を呼び出すと

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). これが成り立たないプラットフォームにコードが移植される可能性がある場合、これは機能しません。

于 2009-10-28T22:33:36.450 に答える
0
//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;

お役に立てれば

于 2010-11-05T18:42:42.087 に答える
0

int を a として渡さないで、 aをvoid*に渡しint*てくださいint。これにより、 を にキャストしvoid*int*参照解除されたポインターを にコピーできますint

int x = *static_cast<int*>(arg);
于 2009-10-28T22:23:44.503 に答える
0

あなたが望むかもしれないのは

int x = reinterpret_cast<int>(arg);

void *これにより、 をとして再解釈できますint

于 2009-10-28T22:28:53.543 に答える
0

関数ポインターは void* (およびその他の非関数ポインター) と互換性がありません

于 2015-07-29T19:53:45.313 に答える
-3

これは、64 ビットのポインターを 32 ビットの整数に変換しているため、情報が失われるためです。

代わりに64ビット整数を使用できますが、通常は正しいプロトタイプで関数を使用し、関数タイプをキャストします。

void thread_func(int arg){
...
}

そして私はこのようなスレッドを作成します:

pthread_create(&tid, NULL, (void*(*)(void*))thread_func, (void*)arg);
于 2009-10-28T22:22:39.860 に答える