itsource

C에서 casting void 포인터는 언제 필요합니까?

mycopycode 2023. 10. 9. 22:34
반응형

C에서 casting void 포인터는 언제 필요합니까?

Mitchell, Oldham, Samuel의 Advanced Linux Programming을 살펴보았습니다.저는 pthreads의 섹션에서 보이드 포인터와 캐스팅에 대해 저를 혼란스럽게 하는 것을 보았습니다.

인수를 pthread_create()로 전달하면 함수가 예상하는 것임에도 불구하고 포인터를 무효 포인터로 캐스트하지 않습니다.

pthread_create( &thread, NULL, &compute_prime, &which_prime );

여기, which_primeint 타입입니다.

그러나 pthread_join을 사용하여 스레드에서 반환된 값을 취하면 변수를 void 포인터로 캐스팅합니다.

pthread_join( thread, (void*) &prime );

여기서 prime은 다시 int형입니다.

주조는 첫 번째 사례가 아니라 두 번째 사례에서 수행되는 이유는 무엇입니까?

가 없습니다.voidC:

6.3.2.3 포인터

1 보이드의 포인터는 포인터에서 불완전한 또는 객체 유형으로 변환되거나 변환될 수 있습니다.미완성 또는 객체 유형의 포인터는 포인터로 변환되어 무효가 되었다가 다시 되돌아 올 수 있습니다. 그 결과는 원래 포인터와 동일하게 비교됩니다.


여기서 유일한 예외는

  • 할 때"%p"s이온 스펙테이터)됩니다에만 지정자를 합니다.void *.
  • 할 때intptr_t아니면uintptr_t다시 A로 돌아가는void *.

두 는 입니다에 입니다.void*보통 실수입니다.예요.

void *primep = ′  // no cast needed
pthread_join(thread, &primep);

.pthread_join가를 .void**그 두번째 논쟁으로서. 더.void*입니다 합니다.입니다void*다로 됩니다.void**자동으로.

그래서, 당신은 언제 캐스팅을 해야 합니까?void*또는 뒤로:

  • ((u)intptr_t);
  • 합니다를 때.void*하여 (void*으로 ( ); 합니다와 합니다.printf.

C에서 임의의 포인터 유형에서 void*로 캐스팅하고 그 반대의 경우는 암묵적으로 수행됩니다.두 번째 예에서는 출연진이 필요 없습니다.

(C++ 캐스팅에서 void*에 대한 포인터는 암시적으로 수행되지만(void*에 캐스팅할 수 없는 함수 포인터와 함수 멤버/메소드 포인터는 제외), 다시 캐스팅하려면 명시적인 캐스팅이 필요합니다.)

문서에 의하면,

int pthread_join(pthread_t thread, void **retval);

.pthread_join가를 .pointer to void*제2의 논변으로서왜냐하면.

pthread_join에서 완료된 스레드에 의해 pthread_exit로 전달된 주소를 반환합니다.일반 포인터만 전달하면 값으로 전달되므로 가리키는 위치를 변경할 수 없습니다.pthread_join으로 전달된 포인터의 값을 변경할 수 있으려면 포인터 자체, 즉 포인터에 대한 포인터로 전달해야 합니다.

, "왜 캐스팅은 첫 번째 케이스가 아니라번째 케이스에서 이루어집니까?"라는 질문에 대해 말씀드리겠습니다.첫번째 경우, 예를 들어,pthread_create, 그것은 기대합니다.void*그 네 번째 변론으로서소패싱&which_prime은연중에 로 전환될 것입니다.void*.

두 번째 경우, 즉,pthread_join, 그것은 기대합니다.void**그리고 우리는 지나가고 있습니다.&prime그래서 컴파일러가 불평을 할 겁니다.그래서, 버그를 우회하기 위해, 저자는 다음과 같은 캐스팅을 전달합니다.void*자동으로 다음으로 변환됩니다.void**.

하지만 이것은 좋은 해결책이 아닙니다.

해결책:

void* prime ; // make prime as void*
pthread_join( thread, &prime );
printf( "%" PRIxPTR "\n", (intptr_t)prime ) ; 
// intptr_t instead of int to get an integer type 
// that's the same size as a pointer

다른 질문에도 같은 코드가 언급된 것 같습니다.

두 번째 링크의 답은 다음과 같습니다.

유효하지 않습니다.많은 시스템에서 발생하는 (int)의 크기 == (void *)의 크기인 경우에는 단순히 작동합니다.

공백 *는 데이터 개체에 대한 포인터를 보유할 수 있는 것으로만 보장됩니다.

여기 그 주제에 대한 C FAQ가 있습니다.

그리고 인용문은 다음과 같습니다.

포인터에서 정수는 어떻게 변환되나요?일시적으로 포인터에 정수를 넣을 수 있습니까, 아니면 그 반대입니까?

포인터에서 정수로의 변환 및 정수에서 포인터로의 변환은 구현 정의되어 있으며(질문 11.33 참조), 포인터를 변경 없이 정수로 변환하고 다시 되돌릴 수 있다는 보장은 더 이상 없습니다.

포인터를 정수로, 또는 정수를 포인터로 강제하는 것은 결코 좋은 관행이 아니었습니다.

언급URL : https://stackoverflow.com/questions/20469958/when-is-casting-void-pointer-needed-in-c

반응형