[Перевод] Нужна ли нам замена языка C?
Язык программирования C даже сегодня находится в списке наиболее популярных используемых языков, несмотря на то, что он был выпущен аж в 1972 году и по современным стандартам имеет довольно много ограничений и изъянов.
Популярность языков программирования в 2020 по индексу TIOBE
И это основная причина, по которой C нужно заменить. На C/C++ написано слишком много критически важного ПО, что имеет обширные последствия. Один из примеров — баги в библиотеках наподобие OpenSSL. Язык C печально известен возникновением таких проблем, как переполнения буфера. C — это язык, позволяющий выстрелить себе в ногу слишком большим количеством способов.
Такое заявление со стороны активного поклонника динамических языков может показаться странным. Однако проблема здесь заключается в безопасности типов. Динамические языки наподобие Python и Julia обычно обнаруживают неправильное применение типов, например, использование integer в конструкции if
. Возможно, динамические языки не отлавливают проблемы на этапе компиляции, но если у них есть система сильной типизации, то многие проблемы обнаруживаются во время выполнения. Это особенно важно для защищённости. Уязвимости защиты по большей мере сводятся к созданию неопределённого поведения, а не к контролируемому завершению.
Но если C настолько плох, то почему его ещё не заменили? На то есть множество причин. Частично его уже заменили. Java, C#, C++ и многие другие языки уже взяли на себя задачи, которые раньше выполнялись на C.
То есть вопрос больше в оставшемся ПО, в котором C по-прежнему доминирует:
- Ядра операционных систем, например, Linux.
- Микроконтроллеры
- Видеокодеки
- Общие низкоуровневые библиотеки наподобие OpenSSL
- Инструменты командной строки Unix наподобие
ls
,cat
иgit
Почему C по-прежнему доминирует в этих областях? Потому что до недавнего времени альтернативы были не особо хороши. Многие языки 90-х, такие как Java, C#, VB.NET и F#, казалось, в основном сосредоточены на создании управляемых языков со сборкой мусора. А это не особо подходящее решение для перечисленных выше примеров.
В 80-х и 90-х начали появляться и другие языки, такие как Perl, Python, Ruby, JavaScript, но ни один из них не подходит для этих задач.
Разумеется, всегда существовали и другие языки со статической типизацией, например, Ada, Modula-2 и т.п. Однако они чаще всего не стремились подстроиться под уже имеющийся у программистов набор навыков или их нельзя было удобно использовать с уже существующими библиотеками C.
Были языки наподобие D, но он имеет уровень сложности C++, что, вероятно, непривлекательно для разработчиков на C. Кроме того, для него изначально требовалась сборка мусора, из-за чего он неприменим во многих упомянутых областях. Никому не нужно, чтобы сборщик мусора срабатывал, когда вы стремитесь поддерживать постоянную частоту кадров.
Я считаю, что одним из первых реальных признаков наличия потребности в современной реинкарнации C и C++ стала растущая популярность Go и Rust. Мы наблюдаем, как многие стандартные инструменты, в прошлом обычно создававшиеся на C или C++, теперь переписываются на Go или Rust. Например, появляется множество инструментов командной строки, написанных на одном из этих языков. Я рассказываю о некоторых таких инструментах здесь. Мы видим, что люди пытаются писать на Rust игровые движки.
Я считаю, что большая часть возможностей по созданию альтернативы C существует сегодня благодаря зрелости LLVM. Существование LLVM означает, что решена сложная задача генерирования высокопроизводительного кода и многоплатформенности. Благодаря нему разработка языков программирования становится доступнее гораздо большему количеству людей.
И Go, и Rust дают нам некоторое представление о том, как можно переосмыслить C/C++; сейчас начинает возникать небольшая кустарная отрасль возможных альтернатив на замену C, вооружённая этим представлением и LLVM:
- Zig, который я довольно подробно описывал здесь.
- Odin — замена C, во многом похожий на Go.
- Язык V. Ещё один C-подобный язык, разработчики которого сильно вдохновлялись Go и Rust.
Чтобы заменить C, язык должен подходить для ниш, в которых всё ещё доминирует C. Не все типы языков для этого подходят. Перечисленные мной языки имеют множество схожих особенностей, благодаря которым они подходят в качестве замены C:
- Простота использования уже имеющихся библиотек C. Ada, Modula-2 и прочие провалились в основном потому, что их нельзя эффективно использовать с огромной экосистемой C.
- Создание языка на основе устоявшихся знаний и договорённостей. Go очень быстро набирает популярность, потому что, несмотря на некоторые изменения синтаксиса, API и способ кодинга очень знакомы программисту на C.
- Нет сборки мусора/ручное управление памятью. C доминирует в областях, где требуется тщательный контроль над использованием памяти. В эту нишу сборка мусора просто не уместится. Именно это помешало Go полностью заменить C.
- Малый размер получающихся двоичных файлов. Как и C, Zig, например, позволяет создавать очень маленькие двоичные файлы. Если вы хотите создать альтернативный язык для сферы встроенных устройств, то нельзя взять язык наподобие Go, создающий большие двоичные файлы.
- Дружественность на уровне систем. Требуется возможность манипулирования битами и байтами. Нужны хорошие бинарные операторы и указатели. Во многих языках, появившихся за последние десятилетия, нет нужной реализации указателей. В Java слово «указатель» превратилось в ругательство, но в Go они частично вернулись.
- Постепенная замена кода на C. Наличие превосходной двоичной совместимости с C.
Давайте рассмотрим последний пункт подробнее. Никто и не подумает начать заниматься заменой существующей инфраструктуры C, если это будет означать необходимость переписывания за раз всей программы с нуля. По моему опыту, переход с Objective-C на Swift был упрощён тем, что можно было переписывать по одному методу за раз, рекомпилировать и тестировать программу.
При помощи языков наподобие Zig это реализовать довольно легко.
Есть множество причин, по которым нам нужно заменить C, а основная причина того, что это не было сделано раньше — отсутствие внимания к этой теме и недостаток подходящих инструментов. И не факт, что на такой шаг обязательно решится крупная организация. Чтобы попытаться это сделать, нужна лёгкость, которой обладает кустарная отрасль, состоящая из отдельных людей. Имея на руках инструмент наподобие LLVM и Go в качестве источника вдохновения, сегодня это вполне можно реализовать.
Считаю ли я лично, что C нужно заменить? Я бы не стал надеяться на быстрые перемены. Это длительный процесс, и у нас пока нет явных победителей. Большие организации не будут переходить на Zig, Odin, V или что-то другое, пока альтернатива не сформируется полностью.
А что вообще подразумевается под «заменой»? Cobol, например, по-прежнему обрабатывает множество наших финансовых транзакций. Тем не менее, я считаю, что Cobol уже заменили в том смысле, что сегодня никто намеренно не выбирает Cobol для новых проектов. А там, где это возможно, люди пытаются мигрировать с него.
Аналогично, большой объём тщательно протестированного кода на C не будет переписываться. Он просто останется с нами. Но, возможно, в будущем мы достигнем этапа, на котором другие языки просто будут предпочитать языку C в тех областях, где он традиционно доминировал.
На правах рекламы
Эпичные серверы для разработчиков и не только! Дешёвые VDS на базе новейших процессоров AMD EPYC и хранилища на основе NVMe дисков от Intel для размещения проектов любой сложности, от корпоративных сетей и игровых проектов до лендингов и VPN. Вы можете создать собственную конфигурацию сервера в пару кликов!