C에서는 void *
다른 포인터 유형으로 a 를 캐스트 할 필요가 없으며 항상 안전하게 승격됩니다. 그러나 C ++에서는 그렇지 않습니다. 예 :
int *a = malloc(sizeof(int));
C에서는 작동하지만 C ++에서는 작동하지 않습니다. (참고 : malloc
C ++ 또는 그 문제 new
를 사용해서는 안되며 대신 스마트 포인터 및 / 또는 STL을 선호해야한다는 것을 알고 있습니다. 이것은 순전히 호기심에서 비롯됩니다.) C ++ 표준 이이 암시 적 캐스트를 허용하지 않는 이유는 무엇입니까? C 표준이하는 동안?
답변
암시 적 유형 변환은 일반적으로 안전하지 않기 때문에 C ++는 C보다 입력에 더 안전한 자세를 취합니다.
대부분의 경우 변환에 오류가있는 경우에도 C는 일반적으로 암시 적 변환을 허용합니다. 왜냐하면 C는 프로그래머가 자신이하는 일을 정확히 알고 있다고 가정하기 때문입니다. 그렇지 않은 경우 컴파일러의 문제가 아니라 프로그래머의 문제입니다.
C ++은 일반적으로 오류가 될 수있는 것을 허용하지 않으며 타입 캐스트로 의도를 명시 적으로 명시해야합니다. C ++은 프로그래머 친화적이려고하기 때문입니다.
실제로 더 많이 입력해야 할 때 얼마나 친숙한 지 묻습니다.
글쎄, 당신은 어떤 프로그램, 어떤 프로그래밍 언어로든 주어진 코드 줄은 일반적으로 쓰여질 것보다 많은 시간을 읽을 것입니다 (*). 따라서 읽기 쉬움은 쓰기 쉬움보다 훨씬 중요합니다. 그리고 읽을 때 잠재적으로 안전하지 않은 변환이 명시 적 유형 캐스트를 통해 눈에 띄면 진행 상황을 이해하고 진행 상황이 실제로 무슨 일이 일어나고 있는지 확실하게 알 수 있습니다.
또한, 명시 적 캐스트를 입력해야하는 불편 함은 경고를 받았지만 결코 본 적이없는 잘못된 할당으로 인해 발생하는 버그를 찾기 위해 몇 시간의 문제 해결 시간의 불편함에 비해 사소한 것입니다.
(*) 이상적으로는 한 번만 작성되지만 재사용에 대한 적합성을 결정하기 위해 누군가가 그것을 검토해야 할 때마다, 그리고 문제 해결이 진행될 때마다 그리고 누군가가 근처에 코드를 추가해야 할 때마다 읽습니다. 그런 다음 근처 코드에 대한 문제 해결이 발생할 때마다. 이것은 “한 번만 쓰고 실행 한 다음 폐기”스크립트를 제외한 모든 경우에 해당되므로 대부분의 스크립팅 언어는 읽기 쉬운 것을 완전히 무시하고 쉽게 작성하는 데 도움이되는 구문을 가지고 있습니다. 펄이 완전히 이해할 수 없다고 생각한 적이 있습니까? 당신은 혼자가 아닙니다. 이러한 언어를 “쓰기 전용”언어로 생각하십시오.
답변
Stroustrup이 말한 내용은 다음과 같습니다. .
C에서는 void *를 T *로 암시 적으로 변환 할 수 있습니다. 이것은 안전하지 않다
그런 다음 void *가 어떻게 위험 할 수 있는지에 대한 예를 보여주고 다음과 같이 말합니다.
… 결과적으로 C ++에서 void *에서 T *를 얻으려면 명시 적 캐스트가 필요합니다. …
마지막으로 그는 다음과 같이 지적합니다.
C에서이 안전하지 않은 변환의 가장 일반적인 용도 중 하나는 malloc ()의 결과를 적절한 포인터에 할당하는 것입니다. 예를 들면 다음과 같습니다.
int * p = malloc (sizeof (int));
C ++에서 typesafe new 연산자를 사용하십시오.
int * p = 새로운 int;
그는 C ++의 디자인과 진화 에서 이것에 대해 더 자세히 설명합니다 .
따라서 언어 디자이너는 이것이 안전하지 않은 패턴이라고 생각하여 불법적으로 만들었고 패턴이 일반적으로 사용되는 방식을 대체하는 다른 방법을 제공했습니다.
답변
C에서는 다른 포인터 유형으로 void *를 캐스트 할 필요가 없으며 항상 안전하게 승격됩니다.
항상 홍보되지만, 거의 안전 하지는 않습니다. .
C ++는 C보다 안전한 유형 시스템을 사용하려고하기 때문에이 동작을 정확하게 비활성화합니다 . 이 동작은 안전 하지 않습니다 .
일반적으로 유형 변환에 대한 다음 3 가지 접근 방식을 고려하십시오.
- 사용자가 모든 것을 쓰도록 강요하므로 모든 전환이 명시 적입니다.
- 사용자가 자신이하는 일을 알고 있다고 가정하고 모든 유형을 다른 유형으로 변환
- 형식이 안전한 제네릭 (템플릿, 새로운 식), 명시적인 사용자 정의 변환 연산자를 사용하여 컴파일러가 완벽하게 볼 수없는 것만 명시 적으로 변환하도록하는 완전한 형식 시스템을 구현합니다.
글쎄, 1은 못 생겼고 어떤 일을하는 데 실질적인 장애물이지만, 큰주의가 필요한 곳에 진정으로 사용될 수 있습니다. C는 구현하기가 더 쉬운 2와 3을 구현하기는 어렵지만 더 안전한 3을 선택했습니다.
답변
정의상, void 포인터는 무엇이든 가리킬 수 있습니다. 모든 포인터를 빈 포인터로 변환 할 수 있으므로 동일한 값에 도달하면 다시 변환 할 수 있습니다. 그러나 다른 유형에 대한 포인터에는 정렬 제한과 같은 제약 조건이있을 수 있습니다. 예를 들어, 문자가 메모리 주소를 점유 할 수 있지만 주소 경계에서 정수를 시작해야하는 아키텍처를 상상해보십시오. 특정 아키텍처에서 정수 포인터는 한 번에 16, 32 또는 64 비트를 계산하여 char *가 실제로 메모리의 동일한 위치를 가리키는 동안 int *의 배수를 가질 수 있습니다. 이 경우, void *에서 변환하면 실제로 복구 할 수없는 비트를 반올림하므로 되돌릴 수 없습니다.
간단히 말해서, void 포인터는 다른 포인터가 가리킬 수없는 것을 포함하여 무엇이든 가리킬 수 있습니다. 따라서 void 포인터로의 변환은 안전하지만 다른 방법은 아닙니다.