실제 이유는 한편으로는 C와 C ++의 의도가 근본적으로 다르고 다른 한편으로는 Java와 C # (몇 가지 예만)의 근본적인 차이에 기인합니다. 역사적 이유로, 여기에서 논의하는 많은 부분이 C ++보다는 C에 대해 이야기하지만 C ++은 C의 직계 후손이므로 C에 대한 내용은 C ++에 동일하게 적용됩니다.
그것들은 대부분 잊혀졌고 (때로는 존재조차 거부 되기는하지만) 최초의 UNIX 버전은 어셈블리 언어로 작성되었습니다. C의 원래 목적의 대부분은 (전적으로는 아니지만) 어셈블리 언어에서 고급 언어로 포트 UNIX를 사용하는 것이 었습니다. 의도의 일부는 어셈블리 언어로 작성해야하는 양을 최소화하기 위해 가능한 한 많은 운영 체제를 더 높은 수준의 언어로 작성하거나 다른 방향에서 보는 것입니다.
이를 달성하기 위해 C 는 어셈블리 언어와 거의 동일한 수준의 하드웨어 액세스 권한을 제공해야 했습니다 . PDP-11 (예를 들어)은 I / O 레지스터를 특정 주소에 매핑했습니다. 예를 들어, 시스템 콘솔에서 키를 눌렀는지 확인하기 위해 하나의 메모리 위치를 읽었습니다. 읽기 대기중인 데이터가있을 때 해당 위치에 1 비트가 설정되었습니다. 그런 다음 다른 지정된 위치에서 바이트를 읽고 누른 키의 ASCII 코드를 검색합니다.
마찬가지로 일부 데이터를 인쇄하려면 지정된 다른 위치를 확인하고 출력 장치가 준비되면 데이터를 다른 지정된 위치에 기록합니다.
이러한 장치의 드라이버 작성을 지원하기 위해 C에서는 정수 유형을 사용하여 임의의 위치를 지정하고 포인터로 변환 한 다음 해당 위치를 메모리에서 읽거나 쓸 수있었습니다.
물론 이것은 매우 심각한 문제가 있습니다. 지구상의 모든 기계가 1970 년대 초반부터 PDP-11과 동일하게 메모리를 배치하는 것은 아닙니다. 따라서 정수를 가져 와서 포인터로 변환 한 다음 해당 포인터를 통해 읽거나 쓰면 아무도 얻을 수있는 것에 대해 합리적인 보장을 제공 할 수 없습니다. 명백한 예를 들어, 읽기와 쓰기는 하드웨어에서 별도의 레지스터에 매핑 될 수 있으므로 무언가를 쓰면 다시 읽고 읽으십시오. 읽은 내용이 쓴 내용과 일치하지 않을 수 있습니다.
떠날 가능성이 몇 가지 있습니다.
- 가능한 모든 하드웨어에 대한 인터페이스를 정의하십시오. 어떤 방식 으로든 하드웨어와 상호 작용하기 위해 읽거나 쓸 수있는 모든 위치의 절대 주소를 지정하십시오.
- 그러한 수준의 접근을 금지하고 그러한 일을하고 싶은 사람은 누구나 어셈블리 언어를 사용해야한다고 선언합니다.
- 사람들이 그렇게 할 수는 있지만 대상 하드웨어에 대한 설명서를 읽고 사용중인 하드웨어에 맞는 코드를 작성하도록하십시오.
이 중 1 개는 충분히 터무니없는 것으로 보이므로 더 이상 논의 할 가치가 없습니다. 2는 기본적으로 언어의 기본 의도를 버리고 있습니다. 따라서 세 번째 옵션은 본질적으로 그들이 합리적으로 고려할 수있는 유일한 옵션으로 남습니다.
상당히 자주 나타나는 또 다른 요점은 정수 유형의 크기입니다. C는 int
아키텍처가 제안한 자연스러운 크기 여야 하는 "위치"를 취합니다 . 따라서 32 비트 VAX를 프로그래밍하는 경우 int
아마도 32 비트이어야하지만 36 비트 Univac을 프로그래밍하는 경우 int
아마도 36 비트이어야합니다. 크기가 8 비트의 배수로 보장되는 유형 만 사용하여 36 비트 컴퓨터 용 운영 체제를 작성하는 것은 합리적이지 않으며 가능하지 않을 수도 있습니다. 어쩌면 나는 피상적이지만 36 비트 시스템 용 OS를 작성하는 경우 36 비트 유형을 지원하는 언어를 사용하고 싶을 것입니다.
언어 관점에서 볼 때 이것은 여전히 더 정의되지 않은 동작으로 이어집니다. 32 비트에 맞는 가장 큰 값을 취하면 1을 추가하면 어떻게됩니까? 일반적인 32 비트 하드웨어에서는 롤오버되거나 하드웨어 오류가 발생할 수 있습니다. 반면에 36 비트 하드웨어에서 실행 중이면 하나만 추가하면됩니다. 언어가 운영 체제 작성을 지원할 경우 두 가지 동작을 모두 보장 할 수 없습니다. 유형의 크기와 오버플로 동작이 서로 다를 수 있도록 허용하면됩니다.
Java와 C #은이 모든 것을 무시할 수 있습니다. 운영 체제 작성을 지원하지 않습니다. 그들과 함께, 당신은 몇 가지 선택이 있습니다. 하나는 하드웨어가 원하는 것을 지원하도록하는 것입니다. 8, 16, 32 및 64 비트 유형을 요구하기 때문에 이러한 크기를 지원하는 하드웨어 만 구축하면됩니다. 또 다른 확실한 가능성은 언어가 기본 하드웨어가 무엇을 원하든 원하는 환경을 제공하는 다른 소프트웨어에서만 실행될 수 있다는 것입니다.
대부분의 경우, 이것은 실제로 하나 또는 선택이 아닙니다. 오히려 많은 구현이 두 가지 모두를 약간 수행합니다. 일반적으로 운영 체제에서 실행중인 JVM에서 Java를 실행합니다. 종종 OS는 C로 작성되고 JVM은 C ++로 작성됩니다. JVM이 ARM CPU에서 실행되는 경우 CPU에 ARM의 Jazelle 확장이 포함되어있어 하드웨어를 Java의 요구에 더 가깝게 맞추므로 소프트웨어에서 수행 할 필요성이 줄어들고 Java 코드가 더 빨리 (또는 더 적게) 실행됩니다. 어쨌든 천천히).
요약
C와 C ++는 의도하지 않은 동작을 수행 할 수있는 수용 가능한 대안을 정의한 사람이 없기 때문에 정의되지 않은 동작을합니다. C #과 Java는 다른 접근 방식을 취하지 만, 그 접근 방식은 C와 C ++의 목표에 맞지 않습니다. 특히, 대부분의 임의로 선택된 하드웨어에서 시스템 소프트웨어 (예 : 운영 체제)를 작성하는 합리적인 방법을 제공하지는 않습니다. 둘 다 일반적으로 작업을 수행하기 위해 기존 시스템 소프트웨어 (보통 C 또는 C ++로 작성)에서 제공하는 기능에 의존합니다.