오늘은 다른 사람의 코드와 같은 I 톱 뭔가 읽을 때 void *func(void* i);
이 무엇을, void*
함수 이름을 각각 변수 유형, 여기 평균을?
또한 언제 이런 종류의 포인터를 사용해야합니까?
malloc
와 calloc
. 맨 페이지는 "... 내장 데이터 형식에 맞게 정렬 된 할당 된 메모리에 대한 포인터를 반환합니다."라고 말합니다.
오늘은 다른 사람의 코드와 같은 I 톱 뭔가 읽을 때 void *func(void* i);
이 무엇을, void*
함수 이름을 각각 변수 유형, 여기 평균을?
또한 언제 이런 종류의 포인터를 사용해야합니까?
malloc
와 calloc
. 맨 페이지는 "... 내장 데이터 형식에 맞게 정렬 된 할당 된 메모리에 대한 포인터를 반환합니다."라고 말합니다.
답변:
에 대한 포인터 void
는 "일반적인"포인터 유형입니다. A void *
는 명시적인 캐스트없이 다른 포인터 유형으로 변환 될 수 있습니다. a를 역 참조 void *
하거나 포인터 산술을 수행 할 수 없습니다 . 먼저 완전한 데이터 유형에 대한 포인터로 변환해야합니다.
void *
동일한 코드에서 다른 포인터 유형으로 작업 할 수 있어야하는 곳에서 종종 사용됩니다. 일반적으로 인용되는 한 가지 예는 라이브러리 함수입니다 qsort
.
void qsort(void *base, size_t nmemb, size_t size,
int (*compar)(const void *, const void *));
base
는 배열의 주소, 배열 nmemb
의 요소 수, size
각 요소의 크기 compar
, 배열의 두 요소를 비교하는 함수에 대한 포인터입니다. 다음과 같이 호출됩니다.
int iArr[10];
double dArr[30];
long lArr[50];
...
qsort(iArr, sizeof iArr/sizeof iArr[0], sizeof iArr[0], compareInt);
qsort(dArr, sizeof dArr/sizeof dArr[0], sizeof dArr[0], compareDouble);
qsort(lArr, sizeof lArr/sizeof lArr[0], sizeof lArr[0], compareLong);
배열 식을 iArr
, dArr
그리고 lArr
암시 함수 호출 포인터 타입으로 배열 형으로 변환되고, 각각의 내재적 "포인터로 변환한다 int
/ double
/ long
"포인터 "를 void
".
비교 함수는 다음과 같습니다.
int compareInt(const void *lhs, const void *rhs)
{
const int *x = lhs; // convert void * to int * by assignment
const int *y = rhs;
if (*x > *y) return 1;
if (*x == *y) return 0;
return -1;
}
을 수락 void *
하면 qsort
모든 유형의 배열로 작업 할 수 있습니다.
사용의 단점은 void *
유형 안전을 창 밖으로 나가고 다가오는 트래픽에 버리는 것입니다. 잘못된 비교 루틴을 사용하지 못하도록 보호 할 방법은 없습니다.
qsort(dArr, sizeof dArr/sizeof dArr[0], sizeof dArr[0], compareInt);
compareInt
인수가 int
s를 가리키고 있지만 실제로 double
s 와 작업하고 있습니다. 컴파일 타임에이 문제를 잡을 방법이 없습니다. 배열이 잘못 배열되어 있습니다.
void*
함수 포인터로 캐스트 할 수 있다고 보장되지는 않습니다 . 그러나 데이터 포인터의 경우 말한 내용이 있습니다.
void *를 사용하면 함수가 특정 유형일 필요가없는 포인터를 사용할 수 있습니다. 예를 들어, 소켓 함수에서
send(void * pData, int nLength)
예를 들어 여러 가지 방법으로 호출 할 수 있습니다.
char * data = "blah";
send(data, strlen(data));
POINT p;
p.x = 1;
p.y = 2;
send(&p, sizeof(POINT));
이와 관련하여 C가 현저하다. void
아무것도 없다고 말할 void*
수 있습니다.
*
차이를 만드는 것은 이 작은 것 입니다.
르네가 지적했다. A void *
는 어떤 위치를 가리키는 포인터입니다. "해석"하는 방법은 사용자에게 있습니다.
C에서 불투명 한 유형을 갖는 유일한 방법입니다. 예를 들어 glib 또는 일반 데이터 구조 라이브러리에서 매우 두드러진 예제를 찾을 수 있습니다. "C 인터페이스 및 구현"에 매우 자세히 설명되어 있습니다.
나는 당신이 완전한 장을 읽고 "얻기"에 대한 포인터의 개념을 이해하려고 노력할 것을 제안합니다.
포인터 http://www.cplusplus.com/doc/tutorial/pointers/ 에 관한이 기사를보고 void pointers 장을 읽을 수 있습니다 .
이것은 C 언어에서도 작동합니다.
void 타입의 포인터는 특별한 타입의 포인터입니다. C ++에서 void는 유형이 없음을 나타내므로 void 포인터는 유형이없는 값을 가리키는 포인터입니다 (따라서 결정되지 않은 길이 및 결정되지 않은 역 참조 속성).
이를 통해 void 포인터가 정수 값 또는 부동 소수점 문자 스트링에서 모든 데이터 유형을 가리킬 수 있습니다. 그러나 그 대가로 그들은 큰 한계가 있습니다 : 그들에 의해 지적 된 데이터는 직접 역 참조 할 수 없습니다 (역 참조 할 유형이 없기 때문에 논리적입니다). 콘크리트 데이터 타입을 가리키는 다른 포인터 타입.
void 포인터를 일반 포인터라고합니다. 샘플 pthread 시나리오로 설명하고 싶습니다.
스레드 함수는 다음과 같은 프로토 타입을 갖습니다.
void *(*start_routine)(void*)
pthread API 디자이너는 스레드 함수의 인수 및 반환 값을 고려했습니다. 그러한 것들이 일반적으로 만들어지면 인수로 보내는 동안 캐스트를 void *로 입력 할 수 있습니다. 마찬가지로 반환 값은 void *에서 검색 할 수 있습니다 (그러나 스레드 함수의 반환 값은 사용하지 않았습니다).
void *PrintHello(void *threadid)
{
long tid;
// ***Arg sent in main is retrieved ***
tid = (long)threadid;
printf("Hello World! It's me, thread #%ld!\n", tid);
pthread_exit(NULL);
}
int main (int argc, char *argv[])
{
pthread_t threads[NUM_THREADS];
int rc;
long t;
for(t=0; t<NUM_THREADS; t++){
//*** t will be type cast to void* and send as argument.
rc = pthread_create(&threads[t], NULL, PrintHello, (void *)t);
if (rc){
printf("ERROR; return code from pthread_create() is %d\n", rc);
exit(-1);
}
}
/* Last thing that main() should do */
pthread_exit(NULL);
}
pthread_exit(NULL);
아닌 대신 전화 하는 이유는 무엇 return 0;
입니까?
a void*
는 포인터이지만 지시하는 유형은 지정되지 않았습니다. 함수에 void 포인터를 전달하면 나중에 함수에서 해당 유형으로 다시 캐스팅하여 사용하려면 해당 유형이 무엇인지 알아야합니다. pthreads
스레드 함수로 사용되는 예제에서 프로토 타입이있는 함수를 사용하는 예제가 표시 됩니다. 그런 다음 void*
인수를 선택한 일반 데이터 유형에 대한 포인터로 사용한 다음 스레드 함수 내에서 사용할 수 있도록 해당 유형으로 다시 캐스트 할 수 있습니다. 빈 포인터를 사용할 때는주의해야합니다. 실제 유형의 포인터로 돌아 가지 않으면 모든 종류의 문제가 발생할 수 있습니다.
이 링크를 사용하면 포인터 http://www.cprogramming.com/tutorial/c/lesson6.html에 대한 자세한 정보를 얻을 수 있습니다 .