2017-01-24 4 views
1

나는 최근에 컴파일러 디자인의 용서를 읽었습니다. 컴파일러에는 기계 독립적 코드를 생성하는 단계 중 하나 인 중간 코드 생성 기능이 포함되어 있습니다. 그렇다면 C가 Java와 같은 플랫폼 독립적 인 언어로 개발되지 않은 이유는 무엇입니까?C가 플랫폼 독립적 인 언어로 만들어지지 않은 이유는 무엇입니까?

+7

디자이너들은 "Java와 같은 플랫폼 독립적 인 언어"를 찾지 않았습니다. 그들은 어셈블러보다 더 높은 수준과 편리함을 원했지만 어셈블러와 비교할 수있는 효율성으로 실행되는 컴팩트 코드를 작성하고 1970 년대의 컴파일러 기술을 사용하여 작고 유지하기 쉬운 시스템을 사용했습니다. 간단한 프로젝트. –

+0

그래서 나중에 플랫폼 의존성 문제가 확인되었습니다. – Curiosity101

+2

"machine independent code"는 아마도 "기계 독립적 인 내부 표현"을 의미하지만 해당 표현으로 인코딩 된 기계 종속 요소가 여전히 존재합니다. 그 말로는, 당신이 무엇을 요구하고 있는지 명확하지 않습니다. – davmac

답변

9

란 드래곤 예약 기술되어 다음 공정이다

  1. 최적화를 수행하는 중간 시스템에 독립적 인 바이트 코드 형식으로 소스 코드를 컴파일하고 IR
  2. 적외선 번역에 분석 타겟 플랫폼의 실제 머신 코드

추가 시스템을 지원하려면 새로운 c 단계 1 및 2를 건드리지 않고도 단계 3의 ode 생성기를 사용할 수 있습니다.

모든 일반적인 C 컴파일러가 이러한 방식으로 작동합니다. 그래서 당신의 질문이 "왜 C 컴파일러가 드래곤 북이 묘사하는 것을하지 않습니까?"라고 대답하면 "그들은 그렇다"입니다.

이제 Java에 대해 언급했습니다. Java 컴파일러가 수행하는 작업은 다음과 같습니다.

  1. Java 코드를 Java 바이트 코드로 컴파일합니다. Java 컴파일러에 관한 한, 이것은 중간 형식은 아니지만 실제 대상 언어입니다.
  2. 최종

이제 바이트 징조를 해석하고 /하거나 JIT - 컴파일 JVM이를 필요한이 바이트 코드를 실행합니다. 최적화 및 분석은 일반적으로 JIT 컴파일 중에 발생합니다. 이것은 Dragon Book에 설명 된 프로세스가 아닙니다.

언어 구현 자의 관점에서 볼 때, 이것은 새로운 목표 시스템을 지원하는 노력을 대폭 변경하지 않습니다. 컴파일러를 변경할 필요가 없으며 대신 JVM을 변경해야합니다. javac 컴파일러에 새 백엔드를 추가하는 대신 JIT 컴파일러에 새 백엔드를 추가합니다. 노력은 기본적으로 동일합니다.

주요 차이점은 Java 프로그래머입니다. 모든 대상 플랫폼에 대해 프로그램을 컴파일하고 각 플랫폼에 대해 패키지를 배포하는 대신 이제 코드를 한 번 컴파일하고 모든 사람에게 결과 패키지를 제공 할 수 있습니다. 이제 코드를 실행하는 사람들은 패키지를 사용할 수 있도록 JVM을 설치해야하므로 기본적으로 프로그래머에서 최종 사용자로 작업을 옮겼지만 JVM을 설치하는 것은 모든 Java 실행하려는 프로그램).

"이제 한 번 쓰기, 모든 곳에서 컴파일"대신 "한 번 컴파일하고 어디서나 실행"할 수 있습니다.

그렇다면 C가 Java와 동일한 기능을 수행하지 않은 이유는 무엇입니까? 공연. 바이트 코드 해석이 느리고 (컴파일 된 코드 실행과 비교할 때) JIT 컴파일은 시작 시간을 증가시킵니다.

+0

이것이 답이라고 생각합니다. OP와 같은 것이 기계 독립적 인 IR에 대해 혼란스러워합니다! = 플랫폼 독립적 인 언어. –

+0

@ArturKink, (C 컴파일러의 맥락에서) 머신 독립적 인 IR이 없다는 것은 말할 것도 없습니다. GIMPLE과 LLVM IR은 모두 플랫폼에 크게 좌우됩니다. –

1

짧은 대답 : 그 당시로서는 실현 가능하지 않았기 때문에.

긴 대답 : Java 플랫폼은 언어 + 가상 머신이고 Java 코드는 ByteCode라는 이름으로 컴파일 된 다음 가상 머신은이 바이트 코드 (어셈블리 언어와 유사 함)를 가져 와서 관련 코드로 변환합니다. 명령은 런타임시 로컬 시스템이 이해할 수있는 기계 명령어를 의미합니다.

모든 아키텍처에는 자체 명령어 세트가 있습니다. 즉, ARM 아키텍처는 x86 아키텍처 용으로 컴파일 된 코드를 이해할 수 없습니다.

(C)의 코드는 기계 명령어로 직접 컴파일되며,이 명령어는 로컬 시스템에서 수행됩니다. Java와 같은 동작을 얻으려면 C를 읽고 런타임시 컴퓨터 코드로 변환하는 일종의 해석기가 있어야합니다.이 코드는 싼 작업이 아니며 시간의 컴퓨터에 너무 많이 사용되었습니다 (C는 1972) 물론이 방법을 구현할 수있는 다른 방법은 사용자가 사용하기 전에 프로그램을 컴파일하게하는 것입니다. 좋지만 어쩌면 소스 코드를 클라이언트에게 보이게 할 수도 있습니다. 희망적으로 그것들을 약간 명확히하는 .

0

을 제외하고 일 구현 정의의 숫자 남겨에서 (연습을이 크게 플랫폼/ABI가 정의하지만, 엄격하게 할 필요가 없습니다 말해서), C 대부분 플랫폼 독립적 인 언어입니다. 실제로 적절한 런타임 환경을 갖춘 모든 기계 플랫폼에서 실행할 수있는 형식으로 출력을 생성하는 C의 구현 (예 : emscripten)이 있습니다. C로 작성된 소프트웨어가 언어의 구현 정의 (또는 더 나쁘고 정의되지 않은) 측면에 대한 가정을하면, 일부 구현/기계에서는 작동하지 않을 수 있지만, 그 원인은 API/환경/라이브러리의 문제입니다 가정 (예 : POSIX, Windows 또는 glibcisms 가정)은 언어 자체에 대해 이식성이없는 가정을하는 것보다 큽니다.

1

C는 원래 "Write-Once, Compile-Anywhere"언어로 설계되어 작성되었으며, 당시에는 Universal Language에 가깝게 만들었습니다.

프로세서와 아키텍처가 너무 근본적으로 다르고 리소스가 너무 작아서 Java와 같은 범용 가상 시스템의 개념이 불가능했습니다.

하나의 코드베이스가 컴파일러를 통해 실행될 수 있다는 생각과 다른 플랫폼에서 동일한 소프트웨어를 사용한다는 생각은 대단했습니다.

+3

P 코드가 존재하지 않는다고해서 (예를 들어) 그 개념에 대한 믿을 수 없을 정도의 날들과 모순이되지는 않습니까? – rici

2

C는 처음에는 특정 시스템과 관련된 특정 사용 사례를 위해 설계되었습니다. 플랫폼 독립적 인 가상 머신으로 구현 된 언어 BCPL에 기반하고 있지만 C의 목표는 운영 체제와 같은 저수준 코드를 작성할 수 있어야한다는 것이 었습니다. 대상 컴퓨터의 특정 기능, 특히 개별 바이트를 직접 주소 지정하는 기능을 이용할 수 있어야합니다. 반대로 BCPL의 기본 아키텍처는 철저하게 단어 지향적입니다.

벨 연구소 (Bell Labs)가 새로운 언어로 유닉스 운영체제를 신속하게 재 구현할 수 있다는 사실은 그 인기를 확실하게 공헌했다. (적어도 그 이유는 내가 처음에 그것을 배웠습니다.언어의 광범위한 보급을 허용하기 위해 컴파일러 버전은 드래곤 북 (Dragon Book)에 요약 된 아키텍처에 따라 작성되었으며 초기 생성 가상 머신 코드는 대상 머신 용 코드를 생성하는 데 사용됩니다. 이 휴대용 C 컴파일러는 수년간 참조 구현이었으며 계속 사용할 수 있습니다.

C와 같은 다른 언어들, 특히 파스칼은 플랫폼 독립적 인 가상 머신을 목표로 삼은 전술을 사용했으며, 가상 머신 코드를 "P 코드"라고 부르는 경우가 많았습니다. Niklaus Wirth의 Pascal 프로젝트가 그들의 목표 아키텍처.

GCC는 가상 컴퓨터를 그대로 사용하지는 않지만, 컴퓨터 수준의 독립적 인 내부 표현을 생성하여 시작하여 컴파일러를 새로운 archutectures로 이식하는 작업을 단순화합니다. 물론 Clang 컴파일러는 다양한 구체적인 기계 코드로 변환되거나 직접 해석 될 수있는 LLVM (저수준 가상 머신) 코드를 생성합니다.