code

오류 : 'void *'에서 'int'로 캐스트하면 정밀도가 손실됩니다.

codestyles 2020. 12. 11. 08:13
반응형

오류 : 'void *'에서 'int'로 캐스트하면 정밀도가 손실됩니다.


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일반적으로 이것을 캐스팅하는 적절한 방법은 없습니다 . C99 표준 라이브러리 제공 intptr_tuintptr_t같은 캐스트를 수행 할 필요성에 대해 오는 때마다 가정되는 형식 정의가 사용된다. 표준 라이브러리 (C99가 아니더라도)가 이러한 유형을 제공하는 경우 사용하십시오. 그렇지 않은 경우 플랫폼에서 포인터 크기를 확인하고 이에 따라 이러한 typedef를 정의하고 사용하십시오.


대신에:

int x = (int)arg;

사용하다:

int x = (long)arg;

대부분의 플랫폼에서 포인터와 long은 같은 크기이지만 int와 포인터는 64 비트 플랫폼에서 같은 크기가 아닙니다. 당신이 (변환하는 경우 void*에) ( long) 더 정밀도, 다음 (할당하여 손실되지 long가 (에) int), 제대로 맞게 수를 자릅니다.


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 *로 다시 변환하는 것은 (모든 곳에서) 잘 지원됩니다.

따라서 결과적으로 포인터를 동적으로 생성하고 사용하는 것이 오류가 적을 수 있습니다. 누출되지 않도록 사용 후 포인터를 삭제하는 것을 기억하십시오.


긴 캐스트를 사용하는 대신 size_t로 캐스트해야합니다.

int val = (int) ((size_t) arg);


적절한 방법은 다른 pointer type. 를로 변환하는 void*것은 int작동하거나 작동하지 않을 수있는 이식 불가능한 방법입니다! 반환 된 주소를 유지해야하는 경우 void*.


나도이 문제를 만난다.

ids [i] = (int) arg; // 여기에 오류가 발생합니다. => 아래로 변경합니다.

ids [i] = (uintptr_t) 인수;

그러면 계속 컴파일 할 수 있습니다. 어쩌면 당신도 이것을 시도 할 수 있습니다.


64 비트 포인터를 32 비트 정수로 저장하는 "올바른"방법은 없습니다. 문제는 캐스팅이 아니라 대상 유형이 포인터의 절반을 잃는 것입니다. 내부 int저장된 32 비트 는 스레드 함수에 대한 포인터를 재구성하기에 충분하지 않습니다. 대부분의 답변은 논쟁에서 쓸모없는 32 비트를 추출하려고합니다.

으로 페루 치오는 말했다 INT는 교체해야 intptr_t프로그램이 의미있게합니다.


다음과 같이 스레드 생성 함수를 호출하면

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). 코드가 이것이 유지되지 않는 플랫폼으로 이식 될 가능성이 있다면 작동하지 않습니다.


가장 안전한 방법 :

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

long모든 컴퓨터의 Linux에서 포인터 크기를 보장합니다. Windows는 64 비트에서만 32 비트 길이를 가지고 있습니다. 따라서 64 비트의 경우 창 long long대신 로 변경해야합니다 long. 그래서 reinterpret_cast그것을 long유형으로 static_cast캐스트 한 다음 안전하게 캐스트 long했습니다 int. 준비가되면 데이터를 자릅니다.


나는 구조를 만들고 그것을 pthread_create에 void *로 전달할 것입니다.

struct threadArg {
    int intData;
    long longData;
    etc...
};


threadArg thrArg;
thrArg.intData = 4;
...
pthread_create(&thread, NULL, myFcn, (void*)(threadArg*)&thrArg);


void* myFcn(void* arg)
{
    threadArg* pThrArg = (threadArg*)arg;
    int computeSomething = pThrArg->intData;
    ...
}

있다는 사실을 숙지 thrArg이 까지 존재한다 () myFcn 을 사용합니다.


당신이 원하는 것은

int x = reinterpret_cast<int>(arg);

이것은 당신이 재 해석 할 수 있습니다 void *int로서 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;

도움이 되었기를 바랍니다


Don't pass your int as a void*, pass a int* to your int, so you can cast the void* to an int* and copy the dereferenced pointer to your int.

int x = *static_cast<int*>(arg);

In my case, I was using a 32-bit value that needed to be passed to an OpenGL function as a void * representing an offset into a buffer.

You cannot just cast the 32-bit variable to a pointer, because that pointer on a 64-bit machine is twice as long. Half your pointer will be garbage. You need to pass an actual pointer.

This will get you a pointer from a 32 bit offset:

int32 nOffset   = 762;       // random offset
char * pOffset  = NULL;      // pointer to hold offset
pOffset         += nOffset;  // this will now hold the value of 762 correctly
glVertexAttribPointer(binding, nStep, glType, glTrueFalse, VertSize(), pOffset);

A function pointer is incompatible to void* (and any other non function pointer)


Well it does this because you are converting a 64 bits pointer to an 32 bits integer so you loose information.

You can use a 64 bits integer instead howerver I usually use a function with the right prototype and I cast the function type : eg.

void thread_func(int arg){
...
}

and I create the thread like this :

pthread_create(&tid, NULL, (void*(*)(void*))thread_func, (void*)arg);

참고URL : https://stackoverflow.com/questions/1640423/error-cast-from-void-to-int-loses-precision

반응형