void
void의 의미는 "유형이 없음"이고, void *는 "유형이 없는 포인터"로서 모든 데이터 유형을 가리킬 수 있습니다.
void 포인터 사용 사양
①void 포인터는 모든 유형의 데이터를 가리킬 수 있습니다. 즉, 모든 데이터 유형의 포인터를 사용하여 void 포인터에 값을 할당할 수 있습니다. 예:
int *pint
void *pvoid;
pvoid = pint; /* 그러나 pint = pvoid */
다른 유형의 포인터에 할당하려면 pint = (int *)pvoid;
② ANSI C 표준에서는 pvoid++ 또는 pvoid+=1 등과 같은 산술 연산이 허용되지 않습니다. void 포인터이지만 GNU에서는 허용됩니다. 기본적으로 GNU는 void *를 char *와 동일하게 간주하기 때문입니다. sizeof( *pvoid )== sizeof( char ).
void의 역할
①함수 반환에 대한 제한 사항.
②함수 매개변수의 제한 사항.
함수에서 값을 반환할 필요가 없는 경우 void 한정자를 사용해야 합니다. 예: void func(int, int);
함수가 매개변수를 허용하지 않는 경우 void 한정을 사용해야 합니다. 예: int func(void).
void 포인터는 모든 유형의 데이터를 가리킬 수 있으므로, 즉 모든 데이터 유형의 포인터를 사용하여 void 포인터에 값을 할당할 수 있으므로 void 포인터도 사용할 수 있습니다. 함수 매개변수로, 함수는 데이터 유형에 대한 모든 포인터를 매개변수로 받아들일 수 있습니다. 예:
void * memcpy( void *dest, const void *src, size_t len );
void * memset( void * buffer, int c, size_t num );
다수 초보자들이 헷갈려하는 부분 C/C++ 언어의 void 포인터형과 void 포인터형을 잘 이해하지 못해서 사용상의 오류가 있습니다. 이 기사에서는 void 키워드의 심오한 의미를 설명합니다. 다음에서는 void 및 void 포인터 유형의 사용 방법과 기술을 자세히 설명합니다.
1. void 포인터 유형 사용 시 주의 사항
ANSI(American National Standards Institute) 표준에 따르면 void 포인터에서는 산술 연산을 수행할 수 없습니다. 즉, 다음 연산은 불법입니다. 🎜>void*pvoid;
pvoid++;//ANSI: Error
pvoid+=1;//ANSI: Error
//ANSI 표준이 이를 식별하는 이유는 알고리즘에 대한 포인터를 주장하기 때문입니다. 작업은 크기를 가리키는 데이터 유형을 알아야 합니다.
//예:
int*pint;
pint++;//ANSI: Correct
pint++의 결과는 sizeof(int)를 늘리는 것입니다.
하지만 유명한 GNU(GNU'sNotUnix의 약어)는 그렇게 생각하지 않습니다. void*의 알고리즘 연산이 char*와 일치한다고 지정합니다.
따라서 GNU 컴파일러에서는 다음 명령문이 정확합니다.
pvoid++; //GNU: 올바른
pvoid+=1; //GNU: 올바른
pvoid++의 실행 결과는 1만큼 증가합니다. .
실제 프로그래밍에서는 ANSI 표준을 충족하고 프로그램의 이식성을 향상시키기 위해 다음과 같이 동일한 기능을 달성하는 코드를 작성할 수 있습니다.
void*pvoid;
(char*)pvoid++; / /ANSI: 올바른; GNU: 올바른
(char*)pvoid+=1;//ANSI: 잘못된 GNU: 올바른
GNU와 ANSI에는 몇 가지 차이점이 있습니다. 일반적으로 GNU는 더 "개방적"입니다. ANSI보다 더 많은 구문을 지원합니다. 하지만 실제 생활에서 디자인할 때는 가능한 한 ANSI 표준을 준수해야 합니다.
로 선언되어야 합니다. 메모리 작업 함수 memcpy 및 memset와 같은 일반적인 함수 프로토타입은 다음과 같습니다. :
void *memcpy(void*dest,constvoid*src,size_tlen);
void*memset(void*buffer,intc,size_tnum);
이런 방식으로 모든 유형의 포인터를 전달할 수 있습니다. memcpy와 memset도 메모리 연산 함수의 의미를 제대로 구현하고 있습니다. 왜냐하면 그것이 연산하는 객체는 메모리 종류에 상관없이 단지 메모리 조각일 뿐이기 때문입니다. memcpy와 memset의 매개변수 유형이 void*가 아니고 char*라면 정말 이상할 것 같습니다! 이러한 memcpy 및 memset은 분명히 "낮은 수준의 재미가 없는 순수" 기능이 아닙니다!
다음 코드는 올바르게 실행됩니다.
//예: memset은 모든 유형의 포인터를 허용합니다.
int intarray[100]
memset(intarray,0,100*sizeof(int));//Intarray 지우기 0
//예: memcpy는 모든 유형의 포인터를 허용합니다
int intarray1[100], intarray2[100];
memcpy(intarray1,intarray2,100*sizeof(int));//intarray2를 다음에 복사 intarray1
흥미로운 점은 memcpy 및 memset 함수도 void* 유형을 반환한다는 것입니다. 표준 라이브러리 함수 작성자는 얼마나 지식이 풍부합니까?
다음 코드는 모두 void를 실제 변수로 만들려고 시도하므로 모두 잘못된 코드입니다.
voida; > function(voida);//Error
void는 추상화를 구현합니다. 이 세상의 변수는 모두 "유형화"되어 있습니다. 예를 들어 사람은 남자이거나 여자입니다(그리고 여자도?).
void의 출현은 단지 추상적인 요구를 위한 것입니다. 객체지향의 "추상 기본 클래스" 개념을 올바르게 이해하면 void 데이터 유형을 이해하기 쉽습니다. 추상 기본 클래스의 인스턴스를 정의할 수 없는 것처럼 void(비유적으로 void를 "추상 데이터 유형"이라고 부르겠습니다) 변수를 정의할 수 없습니다.