Чому так мало компіляторів С?


72

C - одна з найбільш широко використовуваних мов у світі. На нього припадає величезна частка існуючого коду і надалі використовується для величезної кількості нового коду. Його улюблені користувачі, він настільки широко перенесений, що можливість запустити C для багатьох - це неофіційне визначення платформи , і його шанувальники оцінюють за те, що він є "маленькою" мовою з відносно чистим набором функцій.

То де ж усі компілятори?

На робочому столі є (реально) два : GCC та Clang. Думаючи про це кілька секунд, ви, мабуть, пам’ятаєте, що існує і Intel. Є жменька інших, занадто незрозумілих для пересічної людини, щоб назвати їх і майже універсально не намагаються підтримувати останню мовну версію (або часто навіть чітко визначену підмножину мови, просто «підмножину»). Половина членів цього списку - історичні виноски; більшість решти є дуже спеціалізованими і досі фактично не реалізують повну мову. Дуже мало насправді здається, що вони відкриті.

Scheme and Forth - інші малі мови, які улюблені своїми шанувальниками за це - напевно, мають більше компіляторів, ніж фактичні користувачі. Навіть на кшталт SML є більш "серйозні" реалізації, ніж вибрати C. В той час як оголошення нового (незакінченого) компілятора C, що має на меті перевірку, насправді бачить досить негативні відповіді, і ветеранські реалізації намагаються отримати достатню кількість учасників, щоб навіть наздогнати C99.

Чому? Чи так важко реалізувати впровадження C? Це не C ++. Чи просто у користувачів є дуже перекошене уявлення про те, до якої групи складності вона потрапляє (тобто, що вона насправді ближче до C ++, ніж до схеми)?


61
MSVC як і раніше вважається компілятором C89. Напевно, популярніший навіть від Intel.
Rufflewind

22
У Вікіпедії перелічено досить багато компіляторів С. Вони трапляються дуже часто, коли опинишся у вбудованій царині.

113
скільки компіляторів потрібно для складання вашого коду С?
Брайан Чен

76
Питання ґрунтується на помилковій передумові. Аналогові пристрої, armcc, компілятор Брюса, компілятор Bare-C, компілятор Borland, компілятор кланг, компілятор Cosmic C, компілятор CodeWarrior, компілятор dokto, компілятор Ericsson, і я навіть не вийшов перші п’ять літер алфавіту ще. Існує шалено велика кількість компіляторів С. Питання полягає в тому, "чому так мало компіляторів С, якщо ми не вважаємо ці кілька десятків справжніми компіляторами C?" Ви визначили переважну більшість компіляторів С як нецікаві, тому їх не дуже багато.
Ерік Ліпперт

19
Питання "Чому" - це погані запитання для цього сайту в найкращі часи, і "чому б ні?" питання гірші. Якби я зустрічався з вами на вечірці і запитував "так, чому б ви не змагалися з вітрильниками?" Я думаю, що ви правильно вважаєте це дивним питанням. Вам не потрібно наводити виправдання для того, щоб НЕ займатися технічно складним, фізично ризикованим і дуже дорогим хобі. Написання будь-якого нетривіального фрагмента програмного забезпечення є дорогим, складним та ризикованим, а тому потребує величезного мотиватора. Кращим питанням було б "чому так багато компіляторів С?" Дивно, що існує більше одного.
Ерік Ліпперт

Відповіді:


153

Сьогодні вам потрібен справжній компілятор C, який буде оптимізуючим компілятором , особливо тому, що C більше не є мовою, близькою до апаратних, тому що поточні процесори неймовірно складні ( не в порядку , конвеєрні , суперскалярні , зі складними кешами та TLB , отже, потребує планування інструкцій тощо ...). Сьогоднішні процесори x86 не схожі на процесори i386 попереднього століття, навіть якщо обидва здатні запускати один і той же машинний код. Дивіться, що C не є мовою низького рівня (Ваш комп’ютер не є швидкою PDP-11) папером Девіда Чісналла.

Мало хто використовує наївні неоптимізуючі компілятори C, такі як tinycc або nwcc , оскільки вони виробляють код, який у кілька разів повільніше, ніж оптимізація компіляторів.

Кодування оптимізуючого компілятора важко. Зауважте, що і GCC, і Clang оптимізують деяке "нейтральне мовне джерело" представлення коду (Gimple для GCC, LLVM для Clang). Складність хорошого компілятора C не знаходиться у фазі розбору!

Зокрема, зробити компілятор C ++ не набагато складніше, ніж зробити компілятор C: аналіз C ++ та перетворення його на деяке внутрішнє представлення коду є складним (оскільки специфікація C ++ є складним), але добре зрозумілий, але частини оптимізації ще більше складний (всередині GCC: оптимізація середнього класу, мова джерела та нейтраль процесора нейтральна, складають більшість компіляторів, решта врівноважується між передніми кінцевими мовами для декількох мов та зворотними для декількох процесорів). Отже, більшість оптимізуючих компіляторів C також можуть компілювати деякі інші мови, наприклад, C ++, Fortran, D, ... Специфічні частини C ++ GCC складають близько 20% компілятора ...

Також C (або C ++) настільки широко використовується, що люди очікують, що їх код може бути компільований навіть тоді, коли він точно не відповідає офіційним стандартам, які не визначають достатньо точно семантики мови (тому кожен компілятор може мати свою інтерпретацію з неї). Подивіться також на перевірений CompCert компілятор C та статичний аналізатор Frama -C , які піклуються про більш формальну семантику 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 compilersРозкажіть про це команді Visual Studio ...
Мейсон Уілер

18
Microsoft має монополію. Я мав на увазі, що невеликі компанії, що розробляють нові компілятори C, не продадуть їх багато. Чи можете ви назвати недавнього конкурентного конкурента MSVC?
Василь Старинкевич

12
У світі HPC існує безліч фірмових компіляторів. PGCC, NAG та ICC є найбільш широко використовуваними.
Davidmh

37
@MasonWheeler: VS сьогодні дарується безкоштовно (як у пиві). Невільні версії додають інструментарій, але компілятор C у VS2013 однаковий у всіх версіях. Просто немає ринку, навіть для них.
MSalters

3
Але і GCC, і LLVM працюють на значно нижчих представленнях, і вони також оптимізують код C ++ & C (& Ada & Fortran, для GCC). Я б навпаки сказав, що C ++ вимагає більшої оптимізації (особливо при складанні коду за допомогою STL), ніж C!
Базиль Старинкевич

70

Я хотів би оскаржити ваше основне припущення, що існує лише невелика кількість реалізацій C.

Я навіть не знаю C, я не використовую C, я не є членом спільноти C, і все ж, навіть я знаю набагато більше, ніж кілька компіляторів, про яких ви згадали.

Перш за все, є компілятор, який, ймовірно, повністю карликує як GCC, так і Clang на робочому столі: Microsoft Visual C. Незважаючи на натрапи, які і OSX, і Linux робили на робочому столі, і ринок спільного використання iOS та Android "вкрали" від колишніх традиційних користувачів настільних, Windows по - , як і раніше домінуючою настільної ОС, і більшість програм Windows Desktop C, ймовірно , скомпільований з допомогою інструментів Microsoft.

Традиційно, кожен постачальник ОС і кожен постачальник чіпів мали свої компілятори. Microsoft, як постачальник ОС, має Microsoft Visual C. IBM, як постачальник ОС, так і постачальник чіпів, має XLC (який є компілятором системи для AIX за замовчуванням, і компілятором, з якого компілюються і AIX, і i / OS) . Intel має власний компілятор. Sun / Oracle мають власний компілятор у Sun Studio.

Потім з'являються високопродуктивні постачальники компіляторів, такі як PathScale і The Portland Group, чиї компілятори (і бібліотеки OpenMP) використовуються для зчитування чисел.

Цифровий Марс також досі працює. Я вважаю, що Уолтер Брайт має унікальну відмінність - єдину людину на планеті, якій вдалося створити якісний компілятор C ++ (переважно) сам.

І останнє, але не менш важливе, ми маємо всі фірмові компілятори для вбудованих мікроконтролерів. IIRC, щороку продається більше мікроконтролерів, ніж процесори настільних, мобільних, серверних, робочих станцій та мейнфреймів, що продаються за всю історію обчислень разом. Отже, це точно не є нішевими продуктами.

Почесна згадка належить TruffleC , інтерпретатору C (!), Що працює на JVM (!), Написаному за допомогою інтерпретатора AST, що лише на 7% повільніше, ніж GCC та Clang (що швидше за будь-який конкретний орієнтир). Гра на комп'ютерних мовах Бенчмарк, і швидше, ніж обидві мікробензинові позначки. Використовуючи TruffleC, команда Truffle змогла отримати свою версію JRuby + Truffle для виконання розширень Ruby C швидше, ніж реальна реалізація C Ruby!

Отже, це 6 реалізацій на додаток до тих, які ви перерахували, які я можу назвати вгорі голови, навіть не знаючи нічого про C.


1
Поза Microsoft Visual C більшість компіляторів С, про які ви згадуєте, використовуються рідко.
Василь Старинкевич

6
MSVC - це великий компілятор C ++, але для C це важко використовувати та постійно застряг у C89; компілятори мікроконтролерів, як правило, залежать від цілей, застрягли в C89 і химерні; TruffleC ще не доступний (але цікаво, спасибі). Шлях в масштабах та цифровий Марс здаються більше схожими на такі контрприклади, які я шукав, хоча.
Левшенко

8
@Mario мій сенс не в тому, що C89 порушений, але C89 - це не сучасна форма мови; і що це означає менше компіляторів , які уточнений існує.
Левшенко

6
@Leushenko MSVC не назавжди застряг у C89. Були проведені деякі дискусії та слід додати більше функцій C99. Для початку більшість бібліотек C99 підтримується з MSVC 2015, а також декілька мовних функцій (в основному, речі, необхідні для C ++ 11).
Морвен

5
@Morwenn: Мабуть, політика Microsoft полягає в тому, що C99 не вирішує жодних проблем, які C ++ ще не вирішив, і що якщо ви займаєтеся системним програмуванням, ви повинні використовувати C-подібний підмножину C ++ (все, що не вимагає часу виконання або де ви не можете контролювати, куди збирається розміщувати компілятор - важливо, якщо вам потрібно переконатися, що код або дані не створюються в папках із станів, де підключення сторінки вимкнено). Єдині функції C99 - це речі, необхідні в пізніших специфікаціях C ++, і ті, які не потрібно використовувати.
Майк Діммік

8

Скільки компіляторів вам потрібно?

Якщо вони мають різні набори функцій, ви створюєте проблему переносимості. Якщо вони комодітизовані, ви вибираєте або "за замовчуванням" (GCC, Clang або VS). Якщо ви дбаєте про останні 5% продуктивності, у вас є показник відліку.

Якщо ви займаєтесь мовою програмування в оздоровчих цілях або в дослідницьких цілях, швидше за все, це буде більш сучасною мовою. Звідси поширення компіляторів іграшок для Scheme та ML. Хоча OCaml, здається, отримує деяку тягу до неакадемічного використання.

Зверніть увагу, це залежно від мови. Java має по суті ланцюжок інструментів Sun / Oracle та GNU. У Python є різні компілятори, жоден з яких не поважається порівняно зі стандартним перекладачем. Rust and Go мають рівно одну реалізацію. У C # є Microsoft та Mono.


1
Очевидно, що є більш цікаві причини, щоб розробити компілятор ML ... Я просто думав, що спільнота C, мабуть, на три порядки більша, врівноважить цей ефект. Але ти можеш мати рацію, 1000 * 0все-таки 0.
Левшенко

Створення нового компілятора часто пов'язане з фрагментацією спільноти (спричиненою або спричиненою). Наприклад, роздвоєний сервіс egcs vs gcc. Крім того, сумісність із джерелами C зазвичай не нижче 100%.
pjc50

@ pjc50: Спосіб написання стандарту ефективно підрозділяє C на ряд розрізнених діалектів, заснованих на таких речах, як основний тип int, і вимагатимуть від різних компіляторів інтерпретувати один і той же вихідний код дуже різними способами.
supercat

5
Я вважаю, що Go має дві реалізації ( ланцюжок інструментів 6g/ 8g/… та gccgo). Також раніше була дуже цікава власна комерційна реалізація під назвою erGo, яка була: а) вродженою реалізацією Windows Go у той час, коли ні gccgo, ні оригінальний компілятор Go не дуже добре працювали в Windows; б) компанія, що робила ставки на Go, довго до того, як він навіть став 1,0, і в) перша реалізація програми Go, написаної на Go (обидва gccgo та 6g / 8g написані на C). І проект, і компанія зникли, проте, перш ніж вони навіть вийшли із закритої бета-версії.
Йорг W Міттаг

6

C / C ++ є унікальним серед компільованих мов тим, що в ньому є три основні реалізації загальної специфікації.

За правилом відхилення всього, що мало використовується, кожна інша складена мова має від 0 до 1.

І я думаю, що JavaScript є єдиною причиною, яку вам потрібно вказати "компільовано".


2
Мітка "C" застосовується до кількох різних мов; деякі визначають код uint16_t a=48000u; unsigned uint32_t b=(a*a)/2;як присвоєння bзначенню 8192. Деякі визначають його як присвоєння 1152000000. Більшість в даний час вважає його невизначеною поведінкою і, ймовірно, зберігає 3299483648, але не обіцяє з цього приводу.
supercat

1
@supercat: Ах, гарний дивний з переливами та цілими правилами просування. Це залежить від використання 2або 2uочевидно.
Зан Лінкс

1
@ZanLynx: Я не думаю, що існують випадки, коли 2 проти 2u має законне значення; Єдиний випадок, який я знаю, де це може мати значення, стосується Невизначеної поведінки як з 2, так і з 2у.
supercat

3
@supercat: як би ти не визначив поведінку /2u? Ненаписане переповнення визначено (як модуль 2 ^ N для N, визначеного реалізацією), але поділ навіть не може переповнювати.
MSalters

2
Невизначена поведінка виникла б із множення значень, які будуть просуватися до підписаних int, але чий продукт не впишеться в цей тип. Примушення цього результату до непідписаного int, швидше за все, змінить інтерпретацію отриманого значення, але не зведе нанівець не визначене поведінку з попереднього розрахунку.
supercat

5

То яка ваша цільова мова?

Компілятори SML часто орієнтуються на C або щось на кшталт LLVM (або як видно з вашої посилання, JVM або JavaScript).

Якщо ви компілюєте C, це не тому, що ви збираєтесь в JVM. Ти йдеш на щось гірше, ніж C. Набагато гірше. І тоді ви отримуєте копіювати це незначне пекло ще раз у всіх ваших цільових платформах.

І звичайно, C не C ++, але я б сказав, що це ближче до C ++, ніж до Scheme. У нього є свій підмножина невизначеної злочинності поведінки (я дивлюся на вас за розмірами вбудованих типів). І якщо ви викрутите ці деталі (або зробите це "правильно", але несподівано), то у вас є десятиліття існуючого коду життєво важливих систем, який підкаже, наскільки ви страшні. Якщо ви накрутите компілятор SML, він просто не працюватиме - і хтось може помітити. Колись.


SML / NJ та PolyML обидва збирають у машинний код ...
Basile Starynkevitch

2
Як розмір int "Невизначена поведінка"? І чому УБ взагалі буде тягарем для постачальників компіляторів? Єдине справжнє тягар для авторів-компіляторів - це те, що ширини int визначені реалізацією, а не визначеними, тому вам доведеться документувати, що ви зробили.
MSalters

@MSalters Насправді автори-компілятори для встановленої платформи несуть тягар відповідності тому, що робили інші, що йшли до них. Іноді це документується та стандартизується, іноді - ні. Неважко знайти, який розмір є int, але складніше знайти те, що робиться зі значеннями регістру та де зберігаються аргументи під час виклику функції (яка може змінюватися залежно від типів аргументів та типу повернення функції), правил компонування структури, тощо
Випадково832

@MSalters Більшість людей розраховують intна 32 або 64 біти, але це може бути 16 біт. Зовсім не важко створити число поза межами діапазону [−32767, +32767]та intпереповнення UB. Там же char/ shortотримують підвищення int або unsigned int залежно від того, чи intможе представляти кожне значення оригінального типу, що може додатково викликати перетворення intу, unsigned intякщо операнди мали різні типи та були перетворені по-різному, плюс, можливо, інша конверсія, коли результат присвоюється змінній .
Довал

@MSalters Існує достатньо свободи у розмірі стандартних типів і достатньо неявних перетворень, що я б ставлю на облік, що майже для будь-якої нетривіальної програми C існує вибір законних цілих розмірів, які змусять її зробити неправильну річ або спричинить невизначеність поведінка.
Doval
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.