C에서 void가 왜 void가 아닙니까?


25

Java 및 C #과 같은 강력한 형식의 언어에서 void(또는 Void) 메서드의 반환 형식은 다음을 의미합니다.

이 메소드는 아무것도 반환하지 않습니다. 아무것도. 돌아올 수 없습니다. 이 방법으로는 아무것도받지 못할 것입니다.

실제로 이상한 점은 C에서 void리턴 유형 또는 메소드 매개 변수 유형의 의미입니다.

정말 무엇이든 될 수 있습니다. 찾으려면 소스 코드를 읽어야합니다. 행운을 빕니다. 포인터 인 경우 실제로 수행중인 작업을 알아야합니다.

C에서 다음 예를 고려하십시오.

void describe(void *thing)
{
    Object *obj = thing;
    printf("%s.\n", obj->description);
}

void *move(void *location, Direction direction)
{
    void *next = NULL;

    // logic!

    return next;
}

분명히 두 번째 방법은 포인터를 반환합니다.

C가 Java 및 C #보다 오래 되었기 때문에 이러한 언어가 void"아무것도없는"것으로 채택 하고 C가 "아무것도없는 것 (포인터)"으로 사용 된 이유는 무엇입니까?


138
void코드 예제에서 사용 void*하는 질문 제목과 텍스트 는 완전히 다릅니다.

4
또한 Java와 C #은 동일한 개념을 가지고 있음을 명심해야합니다 Object.
Mooing Duck

4
@Mephy 그들은 정확하게 강하게 타이핑되지 않았습니까? 오리 타이핑을 사용하는 C #에서 dynamic거의 사용되지 않는 유형을 의미 합니까?
Axarydax

9
@Mephy : 지난번에 Wikipedia 에 "강력한 유형"이라는 11 개의 상호 모순적인 의미가 있는지 확인했습니다 . 따라서 "C #을 강력하게 입력하지 않았다"는 것은 의미가 없습니다.
Eric Lippert

8
@LightnessRacesinOrbit : 아니요, 요점은 용어에 대한 권위있는 정의가 없다는 것입니다. Wikipedia는 용어 의 올바른 의미 를 알려주 는 규범적인 리소스 가 아닙니다 . 그것은입니다 설명 자원. 11 개의 서로 다른 모순적인 의미를 기술한다는 사실 은 용어를 신중하게 정의하지 않고는 대화에 사용할 수 없다는 증거 입니다 . 그렇지 않으면 대화에서 사람들이 서로 이야기하지 않고 과거에 이야기 할 확률이 매우 높다는 것을 의미합니다.
Eric Lippert

답변:


58

키워드 void(포인터가 아님)는 해당 언어에서 "아무것도 없음"을 의미합니다. 일관성이 있습니다.

언급했듯이 void*원시 포인터 (C 및 C ++)를 지원하는 언어에서 "무엇을 가리키는 포인터"를 의미합니다. 언급 한 바와 같이 void두 가지 다른 의미를 갖기 때문에 이것은 불행한 결정 입니다.

나는 void다른 맥락에서 "아무것도"와 "무엇인가"를 의미하기 위해 재사용하는 역사적 이유를 찾지 못했지만 C는 다른 여러 곳에서 이것을한다. 예를 들어, static상황에 따라 목적이 다릅니다. C 언어에서는 실습에 대해 어떻게 생각하든 상관없이 키워드를 이런 식으로 재사용하는 것이 분명합니다.

Java와 C #은 이러한 문제 중 일부를 수정하기 위해 완전히 휴식을 취하기에 충분히 다릅니다. Java 및 "안전한"C #은 또한 원시 포인터를 허용하지 않으며 쉬운 C 호환성이 필요하지 않습니다 (안전하지 않은 C # 포인터를 허용하지만 대부분의 C # 코드는이 범주에 포함되지 않습니다). 이를 통해 이전 버전과의 호환성에 대해 걱정할 필요가 없습니다. 이를 수행하는 한 가지 방법은 Object모든 클래스가 상속하는 계층 구조의 루트에 클래스 를 도입하는 것이므로 Object참조는 void*유형 문제가 발생하지 않고 원시 메모리 관리없이 동일한 기능을 수행합니다 .


2
집에 도착하면 참고 자료를 제공하겠습니다

4
They also do not allow raw pointers and do not need easy C compatibility.그릇된. C #에는 포인터가 있습니다. 그들은 일반적으로 (그리고 보통 있어야 함) 꺼져 있지만 거기에 있습니다.
Magus

8
그들이 왜 재사용했는지에 관해 void: 분명한 이유는 새로운 키워드를 도입하지 않고 (기존의 프로그램을 손상시킬 가능성이 있음) 것입니다. 그들은 특별 키워드 (예를 소개했다 unknown후) void*의미없는 (그리고 아마도 불법) 구조가 될 것이며, unknown단지의 형태로 법적 것이다 unknown*.
jamesdlin

20
심지어에서 void *, void수단 "아무것도"하지 "아무것도." 를 역 참조 할 수 없으므로 void *먼저 다른 포인터 유형으로 캐스트해야합니다.
oefe

2
@oefe 내가 있기 때문에, 그 머리를 분할하는 의미가 생각 voidvoid*다른 유형 (실제로있다 void"어떤 종류의"입니다). " intin int*은 무언가 를 의미한다 "고 말하는 것만 큼 의미가 있습니다. 아니요, 포인터 변수를 선언하면 "이것은 무언가를 보유 할 수있는 메모리 주소입니다"라고 말합니다. 의 경우 void*"이 주소에는 무언가가 있지만 포인터 유형에서 무언가를 유추 할 수 없습니다"라고 말합니다.

32

void그리고 void*다른 두 가지입니다. voidC에서 반환 값이없는 Java에서와 정확히 같은 의미입니다. A void*는 유형이없는 포인터입니다.

C의 모든 포인터는 역 참조 될 수 있어야합니다. 를 역 참조한 경우 void*어떤 유형을 얻을 수 있습니까? C 포인터는 런타임 유형 정보를 전달하지 않으므로 컴파일시 유형을 알아야합니다.

해당 컨텍스트가 주어지면 역 참조로 논리적으로 할 수있는 유일한 것은 void*무시하는 것 void입니다. 이 유형은 정확히 동작 입니다.


1
"무시"비트에 도달 할 때까지 동의합니다. 반환 된 내용에 해석 방법에 대한 정보가 포함되어있을 수 있습니다. 다시 말해, BASIC 변형의 C에 해당 할 수 있습니다. "이것을 얻을 때, 그것이 무엇인지 알아 내십시오-나는 당신이 무엇을 찾을 수 있는지 먼저 말할 수 없습니다."
Floris

1
또는 다른 방법으로 말하자면, 프로그래머가 정의한 "유형 설명자"를 포인터로 주소가 지정된 메모리 위치의 첫 번째 바이트에 넣을 수 있습니다. 그러면 다음 바이트에서 어떤 데이터 유형을 찾을 수 있는지 알 수 있습니다.
Robert Harvey

1
물론 C에서는 이러한 세부 사항을 언어로 구워 내기보다는 프로그래머에게 맡기기로 결정했습니다. 로부터 언어 의 관점, 그것을 무시가 아닌 다른 작업을 수행하기 위해 다른 무엇을 알 수 없습니다. 이것은 대부분의 유스 케이스에서 정적으로 결정할 수있을 때 항상 유형 정보를 첫 번째 바이트로 포함하는 오버 헤드를 피합니다.
Karl Bielefeldt

4
@RobertHarvey 예, 그러나 당신은 void 포인터를 참조하지 않습니다. void 포인터를 char 포인터로 캐스팅 한 다음 char 포인터를 역 참조합니다.
user253751

4
@Floris가 gcc동의하지 않습니다. 값을 사용하려고 gcc하면 오류 메시지가 표시 error: void value not ignored as it ought to be됩니다.
kasperd

19

아마도 void리턴 타입으로 생각하는 것이 더 유용 할 것입니다 . 그런 다음 두 번째 메소드는 "형식화되지 않은 포인터를 리턴하는 메소드"를 읽습니다 .


도움이됩니다. 수년간 객체 지향 언어로 C를 배우는 (마침내!) 누군가 포인터는 나에게 매우 새로운 개념입니다. 포인터를 반환 할 때 ActionScript 3와 같은 언어와 void거의 동일 *하며 "모든 반환 유형"을 의미합니다.
Naftuli Kay

5
글쎄, void와일드 카드가 아닙니다. 포인터는 메모리 주소 일뿐입니다. (가) 전에 유형 퍼팅 *말한다 "여기가 메모리 주소에서 찾아 낼 것으로 예상 할 수있는 데이터 유형이 포인터에 의해 참조입니다." 퍼팅 void전과 것은 *컴파일러에게 말한다 "나는 유형을 모르는, 그냥 나에게 원시 포인터를 반환하고, 나는 그것이 가리키는 것을 데이터로 무엇을 알아낼 수 있습니다."
Robert Harvey

2
나는 심지어 void*"void"를 지적 한다고 말할 것이다 . 아무 것도 지적하지 않은 베어 포인터. 여전히 다른 포인터처럼 캐스팅 할 수 있습니다.
Robert

11

용어를 조금 강화 해 봅시다.

로부터 온라인 C 2011 표준 :

6.2.5 유형
...
19 void유형은 빈 값 집합으로 구성됩니다. 완료 할 수없는 불완전한 객체 유형입니다.
...
6.3 전환은
...
6.3.2.2 공극

1의 (존재하지 않는) 값이 void식 (유형이 식 void(행 제외) 방식으로 사용되지 않을 것이며, 암시 적 또는 명시 적 전환은 void)에인가되지 않는다 그런 표현. 다른 유형의 표현식이 표현식으로 평가 void 되면 해당 값 또는 지정자가 삭제됩니다. ( void표현식은 부작용에 대해 평가됩니다.)

6.3.2.3 포인터

1void임의의 객체 유형에 대한 포인터로 또는 포인터로 변환 될 수 있습니다. 모든 객체 유형에 대한 포인터는 void로 다시 포인터로 변환 될 수 있습니다. 결과는 원래 포인터와 동일해야합니다.

void표현식 값을 (그것의 부작용이있을 수있다)이 없다. return으로 정의 된 함수가있는 경우 void다음과 같이하십시오.

void foo( void ) { ... }

그런 다음 전화

foo();

값으로 평가되지 않습니다. 결과가 없기 때문에 결과를 아무 것도 할당 할 수 없습니다.

포인터 로는 void본질적으로 "일반"포인터 타입이다; void *명시 적 캐스트를 요구하지 않고 다른 객체 포인터 유형에 값을 할당 할 수 있습니다 (그래서 모든 C 프로그래머가 결과를 캐스트하기 위해 소리를 지 릅니다 malloc).

직접 void *;을 역 참조 할 수 없습니다 . 지정된 객체에 액세스하려면 먼저 다른 객체 포인터 유형에 할당해야합니다.

void포인터는 일반적인 인터페이스를 구현하는 데 사용됩니다. 표준 예제는 qsort형식 인식 비교 기능을 제공하는 한 모든 유형의 배열을 정렬 할 수 있는 라이브러리 함수입니다.

그렇습니다. 두 개의 서로 다른 개념 (값과 일반 포인터가 없음)에 동일한 키워드를 사용하는 것은 혼란 스럽지만 전례가없는 것과는 다릅니다. staticC와 C ++ 모두에서 여러 가지 의미가 있습니다.


9

Java 및 C #에서 void는 메소드의 리턴 유형으로 사용되는 것으로 보입니다.이 메소드는 아무것도 리턴하지 않습니다. 아무것도. 돌아올 수 없습니다. 이 방법으로는 아무것도받지 못할 것입니다.

그 말이 맞습니다. C 및 C ++에도 적합합니다.

C에서 void는 반환 유형 또는 메서드 매개 변수 유형으로 다른 것을 의미합니다.

그 말이 잘못되었습니다. voidC 또는 C ++의 반환 유형은 C # 및 Java에서와 동일한 것을 의미합니다. void와 혼동 하고 void*있습니다. 그들은 완전히 다릅니다.

그것은 것을 혼동되지 voidvoid*평균 전혀 다른 두 가지?

네.

포인터 란 무엇입니까? 무효 포인터 란 무엇입니까?

포인터 A는 값이 될 수있다 역 참조 . 유효한 포인터를 참조 하면 pointed-to type저장 위치 가 제공 됩니다. 무효 포인터가 지적-에 입력 특별한이없는 포인터이다; 저장 위치 를 생성 하기 위해 값을 역 참조 하기 전에보다 구체적인 포인터 유형 으로 변환 해야합니다 .

C, C ++, Java 및 C #에서 void 포인터가 동일합니까?

Java에는 void 포인터가 없습니다. C #은 그렇습니다. 그것들은 C 및 C ++에서와 동일합니다. 포인터 값은 그것에 연관되어 있지 않습니다. 포인터 값은 스토리지 위치를 생성하기 위해 역 참조하기 전에 더 구체적인 유형으로 변환되어야합니다.

C가 Java 및 C #보다 오래 되었기 때문에 이러한 언어가 왜 "nothing"을 의미하는 것으로 void를 채택하고 C가 "nothing 또는 아무것도없는 (포인터 일 때)"로 사용 했습니까?

이 질문은 거짓을 전제로하기 때문에 일관성이 없습니다. 더 좋은 질문을하겠습니다.

void예를 들어, 함수가 절대로 void를 반환하지 않고 서브 루틴이 항상 void를 반환하는 Visual Basic 규칙을 사용하는 대신 Java와 C # 이 유효한 반환 유형 인 규칙을 채택한 이유는 무엇 입니까?

void리턴 유형 인 언어에서 Java 또는 C #으로 오는 프로그래머에게 친숙 합니다.

C #이 왜 void*완전히 다른 의미 의 혼란스러운 규칙을 채택 void했습니까?

void*포인터 유형 인 언어에서 C #으로 오는 프로그래머에게 친숙 합니다.


5
void describe(void *thing);
void *move(void *location, Direction direction);

첫 번째 함수는 아무것도 반환하지 않습니다. 두 번째 함수는 void 포인터를 반환합니다. 그 두 번째 함수를 다음과 같이 선언했을 것입니다.

void* move(void* location, Direction direction);

"void"를 "무의미한"의미로 생각하면 도움이 될 수 있습니다. 의 반환 값 describe은 "의미없는"입니다. 컴파일러에게 반환 값이 의미가 없다고 말했기 때문에 그러한 함수에서 값을 반환하는 것은 불법입니다. 의미가 없기 때문에 해당 함수에서 반환 값을 캡처 할 수 없습니다. void의미가 없기 때문에 변수 유형을 선언 할 수 없습니다 . 예를 들어 void nonsense;말도 안되며 실제로 불법입니다. 또한 void 배열도 의미가 없습니다 void void_array[42];.

void ( void*)에 대한 포인터 는 다릅니다. 배열이 아니라 포인터입니다. void*"의미없는"무언가를 가리키는 포인터를 의미하는 것으로 읽습니다 . 포인터는 "무의미한 것"이므로 이러한 포인터를 역 참조하는 것은 의미가 없습니다. 그렇게하는 것은 실제로 불법입니다. void 포인터를 역 참조하는 코드는 컴파일되지 않습니다.

따라서 void 포인터를 역 참조 할 수없고 void 배열을 만들 수 없다면 어떻게 사용할 수 있습니까? 대답은 모든 유형에 대한 포인터를 (으)로 캐스트 할 수 있다는 것 void*입니다. 일부 포인터를 void*캐스트하고 원래 유형으로 포인터를 캐스트하면 원래 포인터와 동일한 값이 생성됩니다. C 표준은이 동작을 보장합니다. C에서 많은 void 포인터를 보는 주된 이유는이 기능이 객체 지향이 아닌 언어로 정보 숨기기 및 객체 기반 프로그래밍을 구현할 수있는 방법을 제공하기 때문입니다.

마지막으로, 종종 move선언이 void *move(...)아닌 것으로 void* move(...)보이는 이유는 C 대신에 이름 대신 별표를 이름 옆에 두는 것이 일반적인 관례이기 때문입니다. 그 이유는 다음 선언이 큰 문제를 int* iptr, jptr;일으킬 수 있기 때문입니다. 에 대한 두 개의 포인터를 선언한다고 생각하십시오 int. 당신은 아닙니다. 이 선언은에 jptr대한 int포인터가 아닌 포인터를 만듭니다 int. 적절한 선언은 int *iptr, *jptr;선언문마다 하나의 변수를 선언하는 관행을 고수하는 경우 별표가 유형에 속하는 척 할 수 있습니다. 그러나 당신이 척하고 있다는 것을 명심하십시오.


"널 포인터를 역 참조하는 코드는 컴파일되지 않습니다." void 포인터 를 역 참조하는 코드가 컴파일되지 않는다는 것을 의미한다고 생각합니다 . 컴파일러는 널 포인터를 역 참조하지 않도록 보호하지 않습니다. 그것은 런타임 문제입니다.
코디 그레이

@CodyGray-감사합니다! 고쳤다. 널 포인터를 역 참조하는 코드는 (포인터가 아닌 한 void* null_ptr = 0;) 컴파일됩니다 .
David Hammen

2

간단히 말해서 차이는 없습니다 . 몇 가지 예를 들어 보겠습니다.

Car라는 수업이 있다고 가정하겠습니다.

Car obj = anotherCar; // obj is now of type Car
Car* obj = new Car(); // obj is now a pointer of type Car
void obj = 0; // obj has no type
void* = new Car(); // obj is a pointer with no type

나는 여기서 혼동이 당신이 voidvs를 어떻게 정의 할 것인지에 근거한다고 믿는다 void*. 리턴 타입은 void"I 아무것도 반환하지 않음"을 void*의미 하고, 리턴 타입은 "없음 타입의 포인터를 반환합니다" 를 의미합니다.

이것은 포인터가 특별한 경우이기 때문입니다. 포인터 객체는 유효한 객체가 있는지 여부에 관계없이 항상 메모리의 위치를 ​​가리 킵니다. 내 정의 된 유형이없는 무언가 를 가리 void* car키기 때문에 바이트, 단어, 자동차 또는 자전거를 참조 하는지 여부 는 중요하지 않습니다 . 나중에 그것을 정의하는 것은 우리에게 달려 있습니다.void*

C # 및 Java와 같은 언어에서는 메모리가 관리되고 포인터 개념이 Object 클래스로 롤오버됩니다. "아무것도"유형의 객체에 대한 참조를 갖는 대신, 최소한 우리의 객체는 "객체"유형이라는 것을 알고 있습니다. 이유를 설명하겠습니다.

기존 C / C ++에서 객체를 생성하고 포인터를 삭제하면 해당 객체에 액세스 할 수 없습니다. 이것이 메모리 누수 로 알려져 있습니다.

C # / Java에서 모든 것이 객체이므로 런타임에서 모든 객체를 추적 할 수 있습니다. 내 객체가 Car임을 반드시 알 필요는 없으며 Object 클래스가 이미 처리하고있는 기본 정보를 알아야합니다.

프로그래머에게는 C / C ++에서 수동으로 처리해야하는 많은 정보가 Object 클래스에 의해 처리되므로 포인터 인 특수한 경우가 필요하지 않습니다.


"my void *는 정의 된 유형이없는 것을 가리 킵니다"-정확하게는 아닙니다. 길이가 0 인 값에 대한 포인터라고 말하는 것이 더 정확합니다 (거의 0 요소를 가진 배열과 비슷하지만 배열과 관련된 유형 정보조차 없음).
Scott Whitlock

2

나는 C에서 이런 것들을 어떻게 생각할 수 있는지 말하려고 노력할 것이다. C 표준의 공식 언어는 실제로 void쉽지 않다.

유형 void은 유형 중 일류 시민이 아닙니다. 오브젝트 유형이지만 오브젝트 (또는 값), 필드 또는 함수 매개 변수의 유형이 될 수 없습니다. 그러나 함수의 리턴 유형이 될 수 있으므로 표현식의 유형이 될 수 있습니다 (기본적으로 이러한 함수의 호출이지만 조건부 연산자로 구성된 표현식도 void 유형을 가질 수 있음). 그러나 void위의 값 형식으로 최소한의 사용조차도 문을 열어두고 함수 반환을 종료합니다.void 형식의 문 유형의 표현이다 , 명시 적으로 (그것이 비록 C ++로 허용 C에 금지를, 그러나 C에 적용되지 않는 이유로).return E;Evoid

유형의 객체 void가 허용 된 경우 0 비트 (즉, 식의 값에있는 정보의 양)를 갖습니다.void 유형 ). 그러한 객체를 허용하는 주요 문제는 아니지만 다소 쓸모가 없습니다 (크기가 0 인 객체는 포인터 산술을 정의하는 데 약간의 어려움을 겪을 수 있습니다. 그러한 객체의 다른 값 집합에는 하나의 (사소한) 요소가 있습니다. 그것의 가치는 물질이 없기 때문에 사소하게 취해질 수 있지만, 수정 될 수는 없습니다 ( 다른 값이 없음). 따라서 표준은 void빈 값 집합을 포함 한다고 혼동 됩니다. 이러한 유형은 표현할 수없는 표현식을 설명하는 데 유용 할 수 있습니다.C 언어는 실제로 이러한 유형을 사용하지 않지만 평가 (예 : 점프 또는 종료되지 않은 호출)

값 유형으로 허용되고, void적어도 두에 사용 된 직접 "금지"지정하는 방법과 관련이없는 : 지정 (void)기능 유형의 매개 변수 사양으로 그들에게 인수를 제공하는 수단을 (금지를하면서 '()'것이라고 반대로 평균 모든 것에 예, 매개 변수 스펙을 void가진 함수에 인수로 표현식을 제공하는 (void)것은 금지되어 있음) 선언 void *p은 역 참조 표현식 *p이 금지됨을 의미합니다 (그러나 유효한 유형의 표현식이 void아님). 따라서 이러한 사용이 void실제로 void유효한 유형의 표현식 과 일치하지 않는 것이 맞습니다 . 그러나 유형의 객체void*은 실제로 모든 유형의 값에 대한 포인터가 아니며 역 참조 할 수는 없지만 포인터 산술은 금지되어 있지만 포인터로 취급되는 값을 의미합니다. "포인터로 취급"은 실제로 정보의 손실없이 모든 포인터 유형으로 캐스트 될 수 있음을 의미합니다. 그러나 정수 값을 캐스팅하거나 캐스팅하는 데 사용할 수도 있으므로 전혀 가리킬 필요가 없습니다.


엄밀히 말하면, 정보의 손실없이 모든 객체 포인터 유형 에서 캐스트 될 수 있지만 항상 오고 갈 수는 없습니다 . 에서 일반 정보 캐스트에서 void*의 값이 경우 정보가 손실 될 수 있습니다 또 다른 포인터 타입 (UB를하거나, 내가 손을 기억할 수없는), 그러나 void*지금에 캐스팅하고 동일한 유형의 포인터를 캐스팅에서 온 다음, 그렇지 않습니다.
Steve Jessop

0

C # 및 Java에서 모든 클래스는 클래스에서 파생됩니다 Object. 따라서 "무언가"에 대한 참조를 전달할 때마다 유형의 참조를 사용할 수 있습니다Object .

이러한 언어에서는 이러한 목적으로 void 포인터를 사용할 필요 void가 없으므로 여기서 "무언가"또는 "무언가"를 의미 할 필요는 없습니다.


0

C에서는 모든 유형의 포인터를 가질 수 있습니다 [포인터는 참조 유형으로 동작합니다]. 포인터는 알려진 유형의 객체를 식별하거나 임의의 (알 수없는) 유형의 객체를 식별 할 수 있습니다. C의 제작자는 "임의의 유형에 대한 포인터"와 "특정 유형의에 대한 포인터"와 동일한 일반적인 구문을 사용하기로 결정했습니다. 후자의 구문은 유형을 지정하기 위해 토큰이 필요하기 때문에, 이전 구문은 유형이 알려진 경우 해당 토큰이 속하는 곳에 무언가를 두어야합니다. C는이를 위해 키워드 "void"를 사용하기로 결정했습니다.

파스칼에서 C와 마찬가지로 모든 유형의 것들에 대한 포인터를 가질 수 있습니다. 파스칼의 더 인기있는 방언은 또한 "임의의 유형에 대한 포인터"를 허용하지만 "특정 유형의에 대한 포인터"와 동일한 구문을 사용하는 대신 단순히 전자를 다음과 같이 지칭합니다.Pointer 합니다.

Java에는 사용자 정의 변수 유형이 없습니다. 모든 것은 기본 또는 힙 객체 참조입니다. "특정 유형의 힙 오브젝트에 대한 참조"또는 "임의 유형의 힙 오브젝트에 대한 참조"유형의 항목을 정의 할 수 있습니다. 전자는 단순히 특수한 구두점없이 형식 이름을 사용하여 참조임을 나타냅니다 (다른 것이 될 수 없기 때문에). 후자는 유형 이름을 사용합니다.Object .

를 사용하는 void*임의의 타입의 무언가에 대한 포인터에 대한 명칭으로 지금까지 내가 C 및 C ++와 같은 직접 파생 상품에 고유 알고있다; 내가 아는 다른 언어는 분명하게 이름이 지정된 유형을 사용하여 개념을 처리합니다.


-1

키워드 void는 비어있는 것처럼 생각할 수 있습니다 struct( C99에서 빈 구조체는 분명히 허용되지 않습니다 . .NET 및 C ++에서는 0보다 많은 메모리를 차지하며 마지막으로 Java의 모든 것을 클래스라고 생각합니다).

struct void {
};

... 길이가 0 인 유형을 의미합니다. 이것은 함수 호출을 할 때 작동하는 방식입니다.void정수 반환 값에 대해 스택에 4 바이트 정도를 할당하는 대신 ... 하면 스택 포인터가 전혀 변경되지 않습니다 (길이가 0 증가합니다). ).

따라서 다음과 같은 변수를 선언 한 경우 :

int a;
void b;
int c;

... 그리고 당신은 아마도 다음, 그 변수의 주소를했다 b하고 c있기 때문에, 메모리에 같은 장소에 위치 할 수있는 b길이가 제로. 따라서 a void*는 길이가 0 인 내장 유형에 대한 메모리의 포인터입니다. 유용한 바로 그 뒤에 무언가가 있다는 것을 알 수 있다는 사실은 또 다른 문제이며, 현재하고있는 일 (그리고 위험한)을 실제로 알아야합니다.


내가 아는 유일한 컴파일러는 void 유형에 길이를 할당하는 gcc이고 gcc는 길이를 1로 할당합니다.
Joshua
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.