sourcecode

보이드로 변환하거나 그 반대로 변환하는 것은 무엇을 의미합니까?

copyscript 2023. 10. 6. 21:56
반응형

보이드로 변환하거나 그 반대로 변환하는 것은 무엇을 의미합니까?

을 로합니까 합니까?void*아니면 기억의 관점에서 봤을 때 그 반대?가 알기로는 void*는 지정되지 않은 길이의 메모리 블록에 대한 주소입니다.
이것은 사과와 오렌지를 비교하는 것 같습니다.

int myval = 5;
void* ptr = (void*)myval;
printf("%d",(int)ptr);

저는 이것이 사용되는 정확한 맥락을 제시했어야 한다는 것을 깨달았습니다.

int main(int argc, char* argv[]) {
long       thread;  /* Use long in case of a 64-bit system */
pthread_t* thread_handles; 

/* Get number of threads from command line */
if (argc != 2) Usage(argv[0]);
thread_count = strtol(argv[1], NULL, 10);  
if (thread_count <= 0 || thread_count > MAX_THREADS) Usage(argv[0]);

thread_handles = malloc (thread_count*sizeof(pthread_t)); 

for (thread = 0; thread < thread_count; thread++)  
  pthread_create(&thread_handles[thread], NULL, Hello, (void*) thread);  

printf("Hello from the main thread\n");

for (thread = 0; thread < thread_count; thread++) 
  pthread_join(thread_handles[thread], NULL); 

free(thread_handles);
return 0;
}  /* main */

/*-------------------------------------------------------------------*/
void *Hello(void* rank) {
long my_rank = (long) rank;  /* Use long in case of 64-bit system */ 

printf("Hello from thread %ld of %d\n", my_rank, thread_count);

return NULL;
}  /* Hello */

이 코드는 피터 파체초의 병렬 프로그래밍에 관한 책에 나온 것입니다.

int.void *는 의미가 없으므로 포인터에 pointer가 아닌 것을 캐스팅하려고 할 때 수행하면 안 됩니다.C99 표준, 섹션 6.3.2.3 항목 5:

정수는 임의의 포인터 유형으로 변환할 수 있습니다.이전에 지정한 것을 제외하고는 결과가 구현에 정의되어 있고, 올바르게 정렬되어 있지 않을 수 있으며, 참조된 유형의 엔티티를 가리키지 않을 수 있으며, 트랩 표현일 수 있습니다.

캐스팅 수 있습니다.int *.void *(모든 포인터를 다음과 같이 변환할 수 있습니다.void *모든 포인터의 "기본 유형"과 같이 생각할 수 있습니다.

void *.int다:void *,마 64.int32비트만 가능합니다.6C99션 6.3.2.3목 6:

포인터 유형은 모두 정수 유형으로 변환할 수 있습니다.이전에 지정한 것을 제외하고는 구현이 정의된 결과입니다.결과를 정수 형식으로 나타낼 수 없으면 동작이 정의되지 않습니다.결과가 정수 유형의 값 범위에 있을 필요는 없습니다.

을 제공합니다uintptr_t따라서 포인터를 적절한 너비의 숫자 값으로 취급할 수 있습니다.

둘다요.void*및터터)터int대략적으로 말하면 숫자입니다. 수 다보다 int 물론 하지 말아야 물론 불법이며, 가리키는 위치가 유효하지 않은 포인터를 절대로 참조하지 말아야 합니다.

C 표준은 공백 포인터를 적분 타입으로 변환할 수 있어야 한다고 명시하고 있으며, 적분 타입을 다시 공백 포인터로 변환하면 동일한 포인터가 생성됩니다.null 포인터를 정수로 변환해야 값이 0이 되는지 아니면 숫자 리터럴 0만 특수한 것으로 인식되는지 잘 모르겠습니다.많은 구현에서 정수 값은 하드웨어 주소를 나타내지만 표준에서는 이러한 주소를 보장하지 않습니다.하드웨어 주소 0x12345678에 대한 특별한 트랩이 포함된 하드웨어에서 포인터를 정수로 변환하면 하드웨어 주소에서 0x12345678이 차감되고 정수를 포인터로 변환하면 0x12345678이 다시 추가됩니다(따라서 정수 값이 0이면 null 포인터가 됩니다).

많은 경우, 특히 임베디드 컨트롤러용으로 개발할 때 컴파일러 공급업체는 특정 정수 값을 포인터 유형으로 변환할 때 액세스할 하드웨어 주소를 명시적으로 지정합니다.단일 선형 주소 공간을 가진 프로세서에서 정수 값 0x12345678을 포인터로 변환하면 일반적으로 0x12345678을 가리키는 포인터가 생성됩니다. 하드웨어 참조 매뉴얼은 해당 위치에 대해 특별한 사항이 있는지 표시합니다.'흥미로운' 주소 공간이 더 많은 프로세서에서는 하드웨어 주소가 아닌 다른 것을 포인터로 사용해야 할 수도 있습니다.예를 들어, 고풍스러운 IBM PC 컴퓨터에서는 디스플레이 버퍼가 하드웨어 주소 0xB8000에 매핑되었지만 대부분의 컴파일러에서는 주소가 (짧은 거리*)0xB8000000으로 표시됩니다.

이것은 마치 사과와 오렌지를 비교하는 것과 같습니다.이 코드가 작동하는 유일한 방법은 사용자가 이 코드를 앞뒤로 명시적으로 캐스팅하기 때문입니다.

C 컴파일러는 단순히 int의 바이트를 포인터와 뒤 공간에 복사하는 것입니다. 마치 당신이 int에 char를 담을 수 있는 것처럼 말입니다.

이는 플랫폼에서 int가 void *보다 길 경우 번호가 엉망이 될 수도 있습니다.

하고 싶은 , 을 .intptr_t 이 유형은 실제로 정수와 포인터를 모두 저장하도록 설계되었습니다.

포인터 산술을 위해 정수형으로 포인터를 캐스트할 수 있으면 유용합니다.를 들면면.offsetof()으로,합니다.

되는 기본 할 수 가 예를 들어 64 Linux의 경우 gcc를 사용하는 경우에는 그렇지 않습니다.void *크기는 8이고, int는 4입니다.

offsetof매크로는 다음과 같이 정의됩니다.

#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)

리눅스 커널의 이중 링크 리스트 구현에서 눈에 띄게 사용되며, 매우 단순하게 다음과 같이 정의됩니다.

struct list_head { struct list_head *prev, *next; }

이 구조는 다음과 같이 커널 구조 안에 내장됩니다.

struct something {
    //...
    struct list_head list;
    //...
}

목록을 이동할 때 코드는 인코딩 구조에 대한 포인터를 잡아야 합니다.이 작업은 다음과 같이 수행됩니다(간단한 정의).

#define container_of(ptr, type, member) \
    (type *)((char *)ptr - offsetoff(type, member))
#define list_entry(list, type, member) \
    container_of(list, type, member)

그리고 코드에서 여러분은 매우 자주 다음을 보게 될 것입니다.

struct something *s;
list_for_each(listptr, somehead) {
   s = list_entry(listptr, struct something, list);
   //...
}

이런 종류의 매크로와 포인터 산술 없이는 불가능할 것입니다.하지만 그것은 툴체인에 매우 의존적입니다.

만약 어떤 비교를 시도한다면 사과와 오렌지를 비교하는 것과 같습니다.하지만 없습니다.기본적으로, 대부분의 아키텍처에서는 정보의 손실 없이 int를 void pointer에 캐스트할 수 있으며, void pointer도 int에 캐스트할 수 있습니다. 다시 정보의 손실 없이 말이죠.물론 해당 포인터는 의미 있는 메모리 위치를 가리키지 않으므로 재참조를 시도하지 마십시오. 이 포인터는 캐스트 이전에 정수가 포함했던 비트 패턴과 동일한 비트 패턴을 포함하는 변수일 뿐입니다.

언급URL : https://stackoverflow.com/questions/8618637/what-does-it-mean-to-convert-int-to-void-or-vice-versa

반응형