왜 C 컴파일러가 그렇게 적은가?


72

C는 세계에서 가장 널리 사용되는 언어 중 하나입니다. 기존 코드의 상당 부분을 차지하며 방대한 양의 새 코드에 계속 사용됩니다. 그것은 사용자들에게 사랑 받고 있으며, C를 실행할 수 있다는 것은 많은 비공식적 인 플랫폼 정의에 대한 것으로 널리 알려져 있으며, 상대적으로 깨끗한 기능 세트를 가진 "작은"언어로 팬들에게 찬사를 보냅니다.

그렇다면 모든 컴파일러는 어디에 있습니까?

데스크탑에는 GCC와 Clang의 두 가지가 있습니다. 몇 초 동안 그것에 대해 생각하면 아마 인텔도 존재한다는 것을 기억할 것입니다. 소수의 다른 사람들도 있고, 보통 사람이 이름을 짓기가 너무 애매하고, 최근 언어 버전 (또는 종종 잘 정의 된 언어 하위 집합, "단일 하위 집합")을 지원하기 위해 거의 보편적으로 귀찮게하지 않습니다. 이 목록의 구성원 중 절반 은 역사적 각주입니다. 나머지 대부분은 매우 전문화되어 있지만 실제로 전체 언어를 구현하지는 않습니다. 실제로 오픈 소스 인 것처럼 보이는 사람은 거의 없습니다.

팬들에게 사랑받는 다른 작은 언어 인 Scheme and Forth는 아마도 실제 사용자보다 더 많은 컴파일러를 가지고 있습니다. SML 과 같은 것조차도 C보다 선택해야 할 "심각한"구현이 있습니다. 검증을 목표로하는 새로운 (완료되지 않은) C 컴파일러 의 발표는 실제로 부정적인 반응을 보이며 베테랑 구현 은 충분히 기여할 수있는 충분한 기여를 얻기 위해 고군분투합니다. C99.

왜? C를 구현하는 것이 그렇게 어렵습니까? C ++이 아닙니다. 사용자는 그룹에 속하는 복잡성 그룹에 대해 매우 왜곡 된 아이디어를 가지고 있습니까 (예 : 실제로 Scheme보다 C ++에 더 가깝다는 것)?


61
MSVC는 여전히 C89 컴파일러로 간주됩니다. 아마 인텔보다 더 인기가있을 것입니다.
Rufflewind

22
Wikipedia 에는 꽤 많은 C 컴파일러가 나와 있습니다. 임베디드 영역에서 자신을 발견 하면 매우 일반적입니다.

113
C 코드를 컴파일하려면 몇 개의 컴파일러가 필요합니까?
Bryan Chen

76
이 질문은 잘못된 전제에 기초합니다. Analog Devices, armcc, Bruce 's C Compiler, Bare-C Cross Compiler, Borland 컴파일러, clang 컴파일러, Cosmic C 컴파일러, CodeWarrior 컴파일러, dokto 컴파일러, Ericsson 컴파일러 등 알파벳의 처음 5 글자. 이 미친 듯이 큰 C 컴파일러의 수. 문제는 "수십 개의 실제 C 컴파일러로 계산하지 않으면 왜 C 컴파일러가 그렇게 적은가?"입니다. 대다수의 C 컴파일러를 흥미롭지 않은 것으로 정의했기 때문에 그다지 많지 않은 이유가 있습니다.
Eric Lippert

19
"왜"질문은이 사이트에서 가장 좋은 질문이며 "왜 그렇지 않습니까?" 질문이 더 나빠요 파티에서 만나서 "그래, 범선을 왜 경주하지 않니?" 나는 그것이 당신이 그것을 이상한 질문이라고 올바르게 생각한다고 생각합니다. 기술적으로 어렵고 육체적으로 위험하며 비용이 많이 드는 취미에 연루되지 않기 위해 정당성을 제공 할 필요는 없습니다. 사소한 소프트웨어를 작성하는 것은 비싸고 어렵고 위험하므로 막대한 동기 가 필요합니다 . 더 좋은 질문은 "왜 그렇게 많은 C 컴파일러가 있습니까?"입니다. 둘 이상이 있다는 것은 놀라운 일입니다.
Eric Lippert

답변:


153

오늘, 당신이 될 겠다는 C 컴파일러를 필요로 최적화 컴파일러 , 특히 C 하드웨어에 가까운 언어가 더 이상이기 때문에 현재 때문에 프로세서 (믿을 수 없을만큼 복잡 밖으로의 순서 , 파이프 라인 , 슈퍼 스칼라 , 복합와 캐시TLB , 따라서 명령 스케줄링 등 이 필요 합니다 ...). 오늘날의 x86 프로세서는 동일한 머신 코드를 실행할 수 있더라도 이전 세기의 i386 프로세서와 다릅니다. 참고 항목 C는 낮은 수준의 언어가 아닙니다 (컴퓨터가 빠른 PDP-11 아님) 데이비드 키스 넬에 의해 종이.

tinycc 또는 nwcc 와 같은 순진한 비 최적화 C 컴파일러를 사용하는 사람은 거의 없습니다 . 최적화 컴파일러가 제공 할 수있는 것보다 몇 배 느린 코드를 생성하기 때문입니다.

최적화 컴파일러를 코딩하는 것은 어렵습니다. GCC와 Clang은 모두 "원본 언어 중립적"코드 표현 (GCC의 경우 단순, Clang의 경우 LLVM)을 최적화하고 있습니다. 좋은 C 컴파일러의 복잡성은 파싱 단계에 있지 않습니다!

특히 C ++ 컴파일러를 만드는 것은 C 컴파일러를 만드는 것보다 훨씬 어렵지 않습니다 .C ++를 구문 분석하고이를 내부 코드 표현으로 변환하는 것은 복잡하지만 (C ++ 사양이 복잡하기 때문에) 이해하기 쉽지만 최적화 부분은 훨씬 더 많습니다. 복잡함 (GCC 내부 : 미들 엔드 최적화, 소스 언어 및 타겟 프로세서 중립적)은 대부분의 컴파일러를 구성하며 나머지는 여러 언어의 프런트 엔드와 여러 프로세서의 백 엔드간에 균형을 유지 합니다. 따라서 가장 최적화 된 C 컴파일러는 C ++, Fortran, D 등과 같은 다른 언어도 컴파일 할 수 있습니다. GCC의 C ++ 특정 부분은 컴파일러의 약 20 %입니다.

또한 C (또는 C ++)는 너무 널리 사용되어 사람들이 언어의 의미를 정확하게 정의하지 않는 공식 표준을 정확하게 따르지 않아도 코드를 컴파일 할 수 있기를 기대합니다 (따라서 각 컴파일러는 자체 해석을 할 수 있음) 그것의). CompCert에서 입증 한 C 컴파일러와 C의 보다 공식적인 의미론 을 다루는 Frama-C 정적 분석기 도 살펴보십시오 .

그리고 최적화는 긴 꼬리 현상입니다. 몇 가지 간단한 최적화를 구현하는 것은 쉽지만 컴파일러의 경쟁력을 높이지는 못합니다! 경쟁이 치열한 실제 컴파일러를 얻으려면 여러 가지 다양한 최적화를 구현하고이를 현명하게 구성하고 결합해야합니다. 즉, 실제 최적화 컴파일러는 복잡한 소프트웨어 여야합니다. BTW, GCC 및 Clang / LLVM에는 내부에 특수화 된 C / C ++ 코드 생성기가 여러 개 있습니다. 그리고 두 개발자 모두 대규모 개발자 커뮤니티 (수백 명, 주로 정규직 또는 최소 절반 이상)를 운영하는 거대한 짐승 (매년 수백만 개의 소스 코드, 매년 몇 퍼센트 씩 성장률)입니다.

이 없음을 알 수 없는 경우에도, 멀티 스레드 C 컴파일러 (내 지식의 최선을) 일부 (..., 명령 스케줄링 할당을 등록, 예를 들어 내부 절차 최적화) 컴파일러의 일부를 병렬로 실행할 수 있습니다. 그리고 병렬 빌드 make -j는 항상 충분하지는 않습니다 (특히 LTO 사용 ).

또한 C 컴파일러를 처음부터 코딩하는 데 어려움을 겪기 어렵고 이러한 노력은 몇 년 동안 지속되어야합니다. 마지막으로, 대부분의 C 또는 C ++ 컴파일러는 오늘날 무료 소프트웨어 (더 이상 스타트 업이 판매하는 새로운 독점 컴파일러 시장이 아님)이거나 최소한 독점적 인 상품 ( Microsoft Visual C ++ 과 같은 )이며, 자유 소프트웨어가되는 것은 컴파일러에 거의 필요합니다 ( 그들은 많은 다른 조직의 기여가 필요하기 때문에).

C 컴파일러에서 자유 소프트웨어로 처음부터 작업 할 수있는 자금을 얻게되어 기쁩니다. 그러나 오늘날 이것이 가능하다고 믿을만큼 순진하지 않습니다!


14
(there is no more a market for proprietary compilersVisual Studio 팀에게 알려주십시오 ...
Mason Wheeler

18
Microsoft는 독점권을 가지고 있습니다. 새로운 C 컴파일러를 개발하는 소규모 회사는 그다지 많은 것을 팔지 않습니다. MSVC의 최근 독점 경쟁 업체를 지정할 수 있습니까?
Basile Starynkevitch

12
HPC 세계에는 많은 독점 컴파일러가 있습니다. PGCC, NAG 및 ICC가 가장 널리 사용됩니다.
Davidmh

37
@MasonWheeler : VS는 요즘 무료로 제공됩니다 (맥주 에서처럼). 무료 버전은 툴링을 추가하지만 VS2013의 C 컴파일러는 모든 버전에서 동일합니다. 시장도없고 심지어는 시장도 없습니다.
MSalters

3
그러나 GCC와 LLVM은 모두 훨씬 낮은 표현으로 작동하며 C ++ & C (및 GCC의 경우 Ada & Fortran) 코드와 마찬가지로 최적화됩니다. 반대로 C ++은 C보다 더 많은 최적화 (특히 STL을 사용하여 코드를 컴파일 할 때)가 필요하다고 말합니다!
Basile Starynkevitch 2012

70

C 구현의 수가 적다는 기본 가정에 이의를 제기하고 싶습니다.

나는 심지어 C를 모른다. 나는 C를 사용하지 않는다. 나는 C 공동체의 일원이 아니며, 심지어 언급 한 소수의 컴파일러보다 훨씬 더 많은 것을 알고있다.

무엇보다도 데스크톱에서 GCC와 Clang을 완전히 뒤 흔드는 컴파일러가 있습니다 : Microsoft Visual C 이전의 전통적인 데스크톱 사용자와는 달리 Windows는 여전히 지배적 인 데스크톱 OS이며 대부분의 Windows 데스크톱 C 프로그램은 Microsoft 도구를 사용하여 컴파일 될 수 있습니다.

전통적으로 모든 OS 공급 업체와 모든 칩 공급 업체에는 자체 컴파일러가있었습니다. OS 벤더 인 Microsoft는 Microsoft Visual C를 보유하고 있습니다. OS 벤더 및 칩 벤더 인 IBM은 XLC (AIX의 기본 시스템 컴파일러이며 AIX 및 i / OS가 모두 컴파일 된 컴파일러)를 가지고 있습니다. . 인텔에는 자체 컴파일러가 있습니다. Sun / Oracle에는 Sun Studio에 자체 컴파일러가 있습니다.

그런 다음 PathScale 및 Portland Group과 같은 고성능 컴파일러 공급 업체가 있습니다.이 공급 업체는 컴파일러 (및 OpenMP 라이브러리)를 번호 처리에 사용합니다.

디지털 화성은 여전히 ​​사업에 종사하고 있습니다. 월터 브라이트는 지구상에서 유일하게 생산 품질의 C ++ 컴파일러 (대부분)를 스스로 만들었습니다.

마지막으로 임베디드 마이크로 컨트롤러 용 독점 컴파일러가 모두 있습니다. IIRC는 매년 데스크탑, 모바일, 서버, 워크 스테이션 및 메인 프레임 CPU가 컴퓨팅 역사 전체에 판매 된 것보다 더 많은 마이크로 컨트롤러를 판매하고 있습니다. 따라서 이들은 틈새 제품이 아닙니다 .

Truffle AST 인터프리터 프레임 워크를 사용하여 작성된 JVM (!)에서 실행 되는 C 인터프리터 (!) 인 TruffleC 에 대해서는 GCC 및 Clang (특정 벤치 마크에서 가장 빠른 것)보다 7 % 느리게 언급 된 TruffleC 가 있습니다. 컴퓨터 언어 벤치마킹 게임으로 마이크로 벤치 마크보다 빠릅니다. TruffleC를 사용하여 Truffle 팀은 실제 C Ruby 구현보다 Ruby C 확장을 더 빨리 실행하기 위해 JRuby + Truffle 버전을 얻을 수있었습니다!

그래서 이것들은 C에 대해 전혀 알지 않고도 머리 꼭대기에서 이름을 지정할 수있는 나열된 것 외에도 6 가지 구현입니다.


1
Microsoft Visual C 이외에는 언급 한 대부분의 C 컴파일러가 거의 사용되지 않습니다.
Basile Starynkevitch

6
MSVC는 큰 C ++ 컴파일러이지만 C의 경우 C89에서 사용하기 어렵고 영구적으로 고착되지 않습니다. 마이크로 컨트롤러 컴파일러는 일반적으로 타겟에 따라 다르며 C89에 갇혀 있고 기발한 상태입니다. TruffleC는 아직 사용할 수없는 것 같습니다 (그러나 흥미 롭습니다). Pathscale과 Digital Mars는 내가 찾던 반례의 일종처럼 보입니다.
Leushenko 2019

8
@Mario 내 의미는 C89가 깨 졌다는 것이 아니라 C89는 최신 언어가 아닙니다. 이는 최신 컴파일러 더 적음을 의미 합니다.
Leushenko 2019

6
@Leushenko MSVC는 C89에 영구적으로 붙어 있지 않습니다 . 몇 가지 토론이 있었으며 더 많은 C99 기능이 추가되어야합니다. 우선, 대부분의 C99 라이브러리는 MSVC 2015부터 지원되며 몇 가지 언어 기능 (주로 C ++ 11에 필요한 것)도 지원됩니다.
Morwenn

5
@ Morwenn : Microsoft의 정책은 C99가 C ++로 아직 해결되지 않은 문제를 해결하지 않으며 시스템 프로그래밍을 수행하는 경우 C와 같은 C ++ 하위 집합 (런타임 또는 컴파일러가 넣을 위치를 제어 할 수없는 위치-페이징이 비활성화 된 상태에서 코드 또는 데이터가 페이지 아웃되지 않도록 해야하는 경우 중요합니다). C99의 유일한 기능은 이후의 C ++ 사양과 구현할 필요가없는 기능입니다.
Mike Dimmick

8

몇 개의 컴파일러가 필요합니까?

기능 세트가 다른 경우 이식성 문제가 발생합니다. 그들이 상품화되어 있다면 "default"(GCC, Clang 또는 VS)를 선택하십시오. 마지막 5 % 성능에 관심이있는 경우 벤치 마크가 해제됩니다.

레크리에이션 또는 연구 목적으로 프로그래밍 언어 작업을 수행하는 경우보다 현대적인 언어 일 수 있습니다. 따라서 Scheme 및 ML에 대한 장난감 컴파일러의 확산. 비록 OCaml이 장난감이 아닌 비 학술적 사용에 대한 견인력을 얻는 것처럼 보이지만.

이것은 언어마다 많이 다릅니다. Java에는 본질적으로 Sun / Oracle 툴체인과 GNU가 있습니다. 파이썬에는 표준 해석기와 비교할 때 실제로 존중되지 않는 다양한 컴파일러가 있습니다. Rust와 Go는 각각 정확히 하나의 구현을가집니다. C #에는 Microsoft와 Mono가 있습니다.


1
ML 컴파일러를 개발해야 할 더 흥미로운 이유가 있다는 것은 분명합니다. 저는 C 커뮤니티가 아마도 3 배 더 큰 것이 그 결과와 균형을 이룰 것이라고 생각했습니다. 그러나 당신이 옳을 수도, 1000 * 0아직 0.
Leushenko 2019

새로운 컴파일러를 만드는 것은 종종 커뮤니티의 조각화 (에 의한 또는 원인)와 관련이 있습니다. 예를 들어, egcs 대 gcc 유지 관리자 분할. 또한 C 소스 호환성은 100 % 미만인 경향이 있습니다.
pjc50

@ pjc50 : 표준이 작성되는 방식은 C의 기본 유형과 같은 것을 기반으로 여러 분리 된 방언으로 C를 효과적으로 세분화하며 int, 서로 다른 방식으로 동일한 소스 코드를 해석하려면 다른 컴파일러가 필요합니다.
supercat 2019

5
Go에는 두 가지 구현 ( 6g/ 8g/… 툴체인과 gccgo) 이 있다고 생각 합니다. erGo라는 매우 흥미로운 독점적 상용 구현도있었습니다. a) gccgo 나 원래 Go 컴파일러가 Windows에서 잘 작동하지 않았을 때의 Go의 기본 Windows 구현, b) Go에 베팅하는 회사 1.0이되기 전에 c) Go로 작성된 Go의 첫 번째 구현 (gccgo 및 6g / 8g는 모두 C로 작성 됨). 그러나 프로젝트와 회사는 비공개 베타 버전이 나오기 전에 사라졌습니다.
Jörg W Mittag

6

C / C ++는 3 가지 주요 공통 사양 구현이 있다는 점에서 컴파일 된 언어 중에서 독특합니다.

많이 사용되지 않는 것을 무시하는 규칙에 따라 다른 모든 컴파일 언어에는 0에서 1이 있습니다.

그리고 나는 자바 스크립트가 '컴파일'을 지정 해야하는 유일한 이유라고 생각합니다.


2
"C"레이블은 여러 다른 언어에 적용됩니다. 일부는 코드 uint16_t a=48000u; unsigned uint32_t b=(a*a)/2;b값 8192에 지정하는 것으로 정의합니다. 일부 는 코드 를 1152000000을 지정하는 것으로 정의합니다. 현재는 정의되지 않은 동작으로 간주하고 3299483648을 저장할 가능성이 있지만 그와 관련한 약속은 없습니다.
supercat 2019

1
@ supercat : 아, 오버플로 및 정수 승격 규칙이있는 좋은 이상한 것. 그것은 사용에 달려 2이나 2u분명히.
Zan Lynx

1
@ 잔 린스 (ZanLynx) : 2 대 2u가 합법적으로 중요한 경우는 없다고 생각합니다 . 중요한 곳은 2와 2u의 정의되지 않은 동작과 관련이 있습니다.
supercat

3
@ supercat : 어떻게 정의되지 않은 동작을 얻 /2u습니까? 부호없는 오버플로는 (구현 정의 N의 경우 모듈로 2 ^ N으로) 정의되지만 나누기는 오버플로조차 할 수 없습니다.
MSalters

2
정의되지 않은 동작은 부호있는 값으로 승격 int되지만 해당 제품은 해당 유형에 맞지 않는 값의 곱셈에서 비롯됩니다 . 결과를 부호없는 int로 강제하면 결과 값의 해석이 변경 될 수 있지만 이전 계산에서 정의되지 않은 동작을 부정하지는 않습니다.
supercat

5

그래서 당신의 목표 언어는 무엇입니까?

SML 컴파일러는 종종 C 또는 LLVM과 같은 (또는 링크, JVM 또는 JavaScript에서 볼 수있는) 대상을 지정합니다.

C를 컴파일하는 경우 JVM으로 이동하기 때문이 아닙니다. 당신은 C보다 더 나쁜 것에 갈 것입니다. 훨씬 더 나쁩니다. 그런 다음 모든 대상 플랫폼에 대해 사소한 지옥을 여러 번 복제합니다.

그리고 C는 C ++이 아니지만 Scheme보다 C ++에 더 가깝다고 말하고 싶습니다. 정의되지 않은 동작 악의 자체 하위 집합이 있습니다 (내장 유형의 크기를보고 있습니다). 그리고 그 미세한 부분을 망가 뜨리거나 (또는 ​​"정확하게"그러나 예기치 않게 수행한다면) 당신은 얼마나 끔찍한지를 알려주는 중요한 시스템에 수십 개의 기존 코드를 가지고 있습니다. 당신이 SML 컴파일러를 망치는 경우, 그냥 작동하지 않습니다 - 누군가는 수도 알 수 있습니다. 언젠가


SML / NJ 및 PolyML은 모두 머신 코드로 컴파일 중입니다.
Basile Starynkevitch

2
int 크기는 "정의되지 않은 동작"입니까? 어쨌든 UB가 컴파일러 공급 업체에 부담이되는 이유는 무엇입니까? 컴파일러 작성자의 실질적인 부담은 int 너비가 지정되지 않은 구현 정의이므로, 수행 한 작업을 문서화해야한다는 것입니다.
MSalters

@MSalters 실제로, 확립 된 플랫폼을위한 컴파일러 작성자는 이전에 수행 한 다른 작업과 일치해야하는 부담이 있습니다. 때때로 이것은 문서화되고 표준화되며 때로는 그렇지 않습니다. int의 크기를 찾는 것은 쉽지만 레지스터 값으로 수행되는 작업과 함수를 호출 할 때 인수가 저장되는 위치 (인수 유형 및 함수의 반환 유형에 따라 변경 될 수 있음), 구조체 레이아웃 규칙, 등
Random832

@MSalters 대부분의 사람들 int은 32 비트 또는 64 비트를 기대 하지만 16 비트만큼 작을 수 있습니다. 그것은의 범위를 벗어나는 숫자를 생성하는 전혀 어렵지 않습니다 [−32767, +32767]int오버 플로우가 UB입니다. 도 있습니다 char/ short승진하기 int 또는 unsigned int 여부에 따라 int더에서 변환을 트리거 할 수 있습니다 원래 유형의 모든 값을 나타낼 수 intunsigned int피연산자가 다른 유형을했다 다르게 변환있어, 플러스 잠재적으로 또 다른 변환하면 당신이 변수에 결과를 할당 할 때 .
Doval

@MSalters 표준 유형의 크기와 충분한 암시 적 변환에 대한 충분한 여유가 있습니다. 사소한 C 프로그램에 대해서는 잘못된 일을하거나 정의되지 않은 원인이 될 수있는 올바른 정수 크기가 선택됩니다. 행동.
Doval
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.