C에서 casting void 포인터는 언제 필요합니까?
Mitchell, Oldham, Samuel의 Advanced Linux Programming을 살펴보았습니다.저는 pthreads의 섹션에서 보이드 포인터와 캐스팅에 대해 저를 혼란스럽게 하는 것을 보았습니다.
인수를 pthread_create()로 전달하면 함수가 예상하는 것임에도 불구하고 포인터를 무효 포인터로 캐스트하지 않습니다.
pthread_create( &thread, NULL, &compute_prime, &which_prime );
여기, which_prime은 int 타입입니다.
그러나 pthread_join을 사용하여 스레드에서 반환된 값을 취하면 변수를 void 포인터로 캐스팅합니다.
pthread_join( thread, (void*) &prime );
여기서 prime은 다시 int형입니다.
주조는 첫 번째 사례가 아니라 두 번째 사례에서 수행되는 이유는 무엇입니까?
가 없습니다.void
C:
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
'itsource' 카테고리의 다른 글
배열 요소가 존재하는지 확인하려면 어떻게 해야 합니까? (0) | 2023.10.09 |
---|---|
자바스크립트에서 문자열 내부의 공백 제거 (0) | 2023.10.09 |
오라클에서 쿼리 성능을 측정하는 방법 (0) | 2023.10.09 |
우커머스 신규 고객 관리자 알림 이메일 (0) | 2023.10.09 |
database-name에서 대시를 사용하여 bash를 통해 데이터베이스 생성 (0) | 2023.10.09 |