Почему люди используют C, если это так опасно?


132

Я рассматриваю возможность изучения C.

Но почему люди используют C (или C ++), если его можно использовать «опасно»?

Под опасным я имею в виду указатели и другие подобные вещи.

Как и вопрос переполнения стека. Почему функция gets настолько опасна, что ее не следует использовать? , Почему программисты не просто используют Java, Python или другой скомпилированный язык, такой как Visual Basic?


152
Почему повара используют ножи, если их можно использовать «опасно»?
oerkelens

78
С большой властью приходит большая ответственность.
Питер Б

10
Джо Блоу, понтификат много?
Мэтью Джеймс Бриггс

4
Потому что "Back In The Day", когда C стал языком выбора, мы должны были справляться с такими вещами, потому что мы должны были это делать. Интерпретируемые или байт-кодированные языки были слишком медленными, потому что процессоры дня были намного медленнее. (Сегодня я могу купить недорогой настольный ПК с многоядерным процессором 2+ ГГц и 4 ГБ памяти от Dell за 279 долларов. У вас НЕТ ИДЕИ, как это совершенно невероятно для такого парня, как я, для которого ПК на 4 МГц с 640 килобайтами памяти было блаженство ...). Посмотри правде в глаза - закон Мура победил. Игра. Над!
Боб Джарвис

6
@ Боб Джарвис: Игра не окончена. Если вы считаете, что ваш ПК с тактовой частотой 2 ГГц, 4 ГБ - или, если уж на то пошло, кластер из нескольких сотен компьютеров с тактовой частотой 4 ГГц с новейшими графическими процессорами CUDA или чего-то еще - достаточно быстрый, вы просто не решаете достаточно сложные проблемы :-)
jamesqf

Ответы:


246
  1. C предшествует многим другим языкам, о которых вы думаете. Многое из того, что мы теперь знаем о том, как сделать программирование «более безопасным», получено из опыта работы с такими языками, как C.

  2. Многие из более безопасных языков, появившихся после C, для достижения своих целей полагаются на большее время выполнения, более сложный набор функций и / или виртуальную машину. В результате C остается чем-то вроде «наименьшего общего знаменателя» среди всех популярных / основных языков.

    • C - намного более простой в реализации язык, потому что он относительно мал и с большей вероятностью будет работать адекватно даже в самой слабой среде, поэтому многие встроенные системы, которым необходимо разрабатывать свои собственные компиляторы и другие инструменты, с большей вероятностью смогут обеспечить функциональный компилятор для C.

    • Поскольку C такой маленький и простой, другие языки программирования, как правило, взаимодействуют друг с другом, используя C-подобный API. Вероятно, это главная причина, по которой С никогда не умрет, даже если большинство из нас когда-либо взаимодействуют с ним только через оболочки.

  3. Многие из «безопасных» языков, которые пытаются улучшить C и C ++, не пытаются быть «системными языками», которые дают вам почти полный контроль над использованием памяти и поведением во время выполнения вашей программы. Несмотря на то, что все больше приложений в наши дни просто не нуждаются в таком уровне контроля, всегда будет небольшое количество случаев, когда это необходимо (особенно внутри виртуальных машин и браузеров, которые реализуют все эти красивые, безопасные языки для остальные).

    Сегодня существует несколько языков системного программирования (Rust, Nim, D, ...), которые безопаснее, чем C или C ++. Они имеют преимущества задним числом и понимают, что в большинстве случаев такой точный контроль не требуется, поэтому предлагают в целом безопасный интерфейс с несколькими небезопасными перехватчиками / режимами, которые можно переключать, когда это действительно необходимо.

  4. Даже в C мы изучили много правил и руководств, которые, как правило, резко сокращают количество коварных ошибок, которые обнаруживаются на практике. Как правило, невозможно заставить стандарт принудительно применять эти правила задним числом, потому что это может нарушить слишком большой существующий код, но обычно используются предупреждения компилятора, линтеры и другие инструменты статического анализа для обнаружения такого рода легко предотвратимых проблем. Подмножество программ на C, которые передают эти инструменты с летающими цветами, уже намного безопаснее, чем «просто C», и любой компетентный программист на C сегодня будет использовать некоторые из них.


Кроме того, вы никогда не сделаете запутанный Java-конкурс таким же интересным, как и запутанный C-конкурс .


7
«Наименьший общий знаменатель» звучит пренебрежительно. Я бы сказал, что, в отличие от многих гораздо более тяжелых языков, C не требует тонны дополнительного багажа, который вам не нужен, и дает вам молниеносную базу для реализации того, что вам нужно. Это то, что вы имели в виду?
underscore_d

9
«Вы не можете иметь одно без другого»: на самом деле многие новые языки (Rust, Nim, D, ...) пытаются это сделать. Это в основном сводится к сопоставлению «безопасного» подмножества языка с парой «небезопасных» примитивов, когда этот уровень контроля абсолютно необходим. Тем не менее, все они основаны на знаниях, накопленных в C и C ++, поэтому, возможно, следует сказать, что во время разработки C и C ++ вы не могли иметь одно без другого, и в настоящее время есть язык, который пытается разделить их «небезопасные» биты, но они еще не догнали.
Матье М.

6
1) не является действительным пунктом! С взял черты из Алгола 68, который в этом смысле является «безопасным» языком; поэтому авторы знали о таких языках. Другие моменты великолепны.
reinierpost

4
@MatthieuM. Возможно, вы захотите взглянуть на Microsoft Research. За последние десять или два года они выпустили несколько управляемых ОС, в том числе более быстрые (совершенно случайно - основная цель большинства этих исследовательских ОС - безопасность, а не скорость), чем эквивалентные неуправляемые ОС для определенных реальных рабочих нагрузок. , Ускорение происходит в основном из-за ограничений безопасности - статическая и динамическая проверка исполняемых файлов позволяет выполнять оптимизации, недоступные в неуправляемом коде. Здесь есть на что посмотреть, и все источники включены;)
Luaan

3
@Luaan: Мидори выглядит потрясающе; Я всегда с нетерпением жду статей в блоге Джо.
Матье М.

41

Во-первых, C - язык системного программирования. Так, например, если вы пишете виртуальную машину Java или интерпретатор Python, вам понадобится язык системного программирования для их записи.

Во-вторых, C обеспечивает производительность, которой нет у таких языков, как Java и Python. Как правило, высокопроизводительные вычисления в Java и Python используют библиотеки, написанные на высокопроизводительном языке, таком как C, для выполнения тяжелой работы.

В-третьих, C имеет гораздо меньшую площадь, чем такие языки, как Java и Python. Это делает его пригодным для встраиваемых систем, которые могут не иметь ресурсов, необходимых для поддержки больших сред выполнения и требований к памяти таких языков, как Java и Python.


«Язык системного программирования» - это язык, подходящий для создания систем промышленного уровня; Java и Python не являются языками системного программирования. «Именно то, что делает язык системного программирования», выходит за рамки этого вопроса, но язык системного программирования должен обеспечивать поддержку работы с базовой платформой.

С другой стороны (в ответ на комментарии) язык системного программирования не обязательно должен быть хостом. Этот вопрос пришел потому , что первоначальный вопрос задает «почему люди используют C», то первый комментарий спросил «почему бы вам нужен язык , как C» , когда у вас есть PyPy, и я заметил , что PyPy делает фактически использовать C. Таким образом, это Первоначально был актуален для вопроса, но, к сожалению (и сбивает с толку) «самодостаточность» на самом деле не имеет отношения к этому ответу. Извини, что поднял это.

Итак, подведем итог: Java и Python не подходят для системного программирования не потому, что их основные реализации интерпретируются, или потому, что встроенные реализации не являются самостоятельными, а потому, что они не обеспечивают необходимую поддержку для работы с базовой платформой.


19
«если вы пишете виртуальную машину Java или интерпретатор Python, вам понадобится язык системного программирования для их написания». Э - э? Как вы объясните PyPy? Зачем вам такой язык, как C, для написания компилятора, интерпретатора или виртуальной машины?
Винсент Савард

10
Я действительно считаю, что вы утверждали, что вам нужен системный язык программирования для написания виртуальной машины Java или интерпретатора Python, когда вы сказали: «Если вы пишете виртуальную машину Java или интерпретатор Python, вам понадобится язык системного программирования для их записи». Если PyPy вас не устраивает, вы также можете посмотреть любой интерпретатор или компилятор, написанный на Haskell. Или действительно, просто добавьте ссылку, подтверждающую вашу заявку.
Винсент Савард

16
Даже если это все черепахи внизу, что-то вроде PyPy не могло бы существовать без интерпретатора Python, написанного на каком-то другом языке.
Blrfl

18
@Birfl Но это не так много говорит. C не мог бы быть написан без компилятора сборки, и вы не можете написать сборку без аппаратного обеспечения, которое его реализует.
садовник

11
Если PyPy не является «языком системного программирования», потому что где-то задействован компилятор C, то C также не является языком системного программирования, потому что где-то используется ассемблер. На самом деле, не популярно ли сейчас перевод C на какой-то другой язык? например, LLVM

30

Извините, что добавил еще один ответ, но я не думаю, что какой-либо из существующих ответов напрямую относится к вашему первому предложению с указанием:

«Я рассматриваю изучение C»

Почему? Вы хотите сделать то, что C обычно используется сегодня (например, драйверы устройств, виртуальные машины, игровые движки, библиотеки мультимедиа, встроенные системы, ядра ОС)?

Если да, то да, обязательно изучите C или C ++ в зависимости от того, кого из вас интересует. Хотите ли вы выучить это, чтобы у вас было более глубокое понимание того, что делает ваш язык высокого уровня?

Затем вы продолжаете упоминать проблемы безопасности. Вам не обязательно глубокое понимание безопасного C, чтобы сделать последнее, точно так же, как пример кода на языке более высокого уровня может дать вам суть, не будучи готовым к работе.

Напишите немного кода на C, чтобы понять суть. Затем положите его обратно на полку. Не беспокойтесь о безопасности, если вы не хотите писать производственный C-код.


2
Отличная работа, отвечая на то, что кажется реальным вопросом! Отличный способ оценить C / C ++ и «более безопасные» языки для всего, что они есть на самом деле, - это попробовать написать что-то вроде простого движка базы данных. Вы получите хорошее представление о каждом из подходов, которые вы попробуете, и увидите, к чему это вас ведет. Вы увидите, что кажется естественным в любом из них, и вы обнаружите, где естественный подход терпит неудачу (например, очень легко «сериализовать» необработанные данные в C - просто записать данные !;, но результат не переносимый, поэтому может иметь ограниченное использование). Понимание безопасности сложно, потому что с большинством проблем может быть трудно столкнуться.
Луаан

1
Точно @Luaan, научиться копировать строку с помощью указателей дает вам идею, научиться делать это безопасно - это другой уровень, а в зависимости от целей возможно ненужный.
Джаред Смит

2
Это был не совсем вопрос. Но это было полезно для решения проблемы. Я решил сделать это. Я желаю узнать больше о внутренней работе всего, на чем строится. И я просто люблю программировать. Таким образом я надеюсь лучше понять внутреннюю работу компьютеров. Это просто для удовольствия.
Тристан

10
Я не согласен с последним предложением. Узнайте, как сделать это правильно, прежде чем развивать вредные привычки.
glglgl

2
@glglgl IDK, если я читаю (или пишу) фрагмент кода JavaScript в Интернете, я делаю это с пониманием того, что он не готов к работе: он не будет обрабатывать исключения, это может быть O (n ^ 2) и т. д. Нет этого необходимо, чтобы понять суть. Все это необходимо для производственного кода. Почему это отличается? Я могу написать наивный C для моего собственного назидания, в то же время понимая интеллектуально, что, если бы я хотел выпустить это, мне нужно было бы сделать намного больше работы.
Джаред Смит

14

Это ОГРОМНЫЙ вопрос с множеством ответов, но вкратце, каждый язык программирования специализирован для различных ситуаций. Например, JavaScript для Интернета, C для низкого уровня, C # для чего угодно Windows и т. Д. Это помогает узнать, что вы хотите сделать, когда вы знаете, программирование, чтобы решить, какой язык программирования выбрать.

Чтобы обратиться к последнему пункту, почему C / C ++ вместо Java / Python часто сводится к скорости. Я создаю игры, и Java / C # только недавно достигли скоростей, которые достаточно хороши для запуска игр. В конце концов, если вы хотите, чтобы ваша игра работала со скоростью 60 кадров в секунду, и вы хотите, чтобы ваша игра выполняла много задач (рендеринг является особенно дорогим), то вам нужен код для максимально быстрой работы. Python / Java / C # / Многие другие работают на «интерпретаторах», дополнительном слое программного обеспечения, которое обрабатывает все утомительные вещи, которые не делает C / C ++, такие как управление памятью и сборкой мусора. Эти дополнительные издержки замедляют работу, поэтому почти каждая крупная игра, которую вы видите, была сделана (в любом случае за последние 10 лет) на C или C ++. Есть исключения: игровой движок Unity использует C # *, а Minecraft использует Java, но это исключение, а не правило. В общем,

* Даже Unity - это не все C #, огромные его части - C ++, и вы просто используете C # для своего игрового кода.

РЕДАКТИРОВАТЬ Чтобы ответить на некоторые комментарии, которые появились после того, как я опубликовал это: Возможно, я слишком сильно упрощал, я просто давал общую картину. С программированием ответ никогда не бывает простым. Есть интерпретаторы для C, Javascript может работать вне браузера, а C # может работать практически на чем угодно благодаря Mono. Различные языки программирования специализированы для разных областей, но некоторые программисты где-то наверняка выяснили, как заставить любой язык работать в любом контексте. Поскольку ОП, казалось, не знал много программирования (предположение с моей стороны, извините, если я ошибаюсь), я пытался сделать свой ответ простым.

Что касается комментариев о том, что C # почти такой же быстрый, как C ++, ключевое слово там почти. Когда я учился в колледже, мы гастролировали по многим игровым компаниям, и мой учитель (который целый год поощрял нас переходить с C # на C ++) спрашивал программистов в каждой компании, к которой мы обращались, почему C ++ по сравнению с C # и каждая из них сказал C # слишком медленно В целом он работает быстро, но сборщик мусора может снизить производительность, потому что вы не можете контролировать, когда он работает, и он имеет право игнорировать вас, если он не хочет работать, когда вы рекомендуете это делать. Если вам нужно что-то с высокой производительностью, вам не нужно что-то столь непредсказуемое.

Чтобы ответить на мой комментарий «только что достиг скорости», да, большая часть увеличения скорости C # происходит от более качественного оборудования, но по мере того, как улучшились .NET Framework и компилятор C #, там были некоторые ускорения.

О «играх пишут на том же языке, что и движок» комментируют, это зависит. Некоторые из них, но многие написаны на гибридных языках. Unreal может использовать UnrealScript и C ++, Unity поддерживает C # Javascript и Boo, многие другие движки, написанные на C или C ++, используют Python или Lua в качестве языков сценариев. Там нет простого ответа.

И только из-за того, что мне мешало читать «кому какое дело, если ваша игра работает на скорости 200 или 120 кадров в секунду», если ваша игра работает быстрее, чем 60 кадров в секунду, вы, вероятно, тратите время процессора, так как средний монитор даже не обновляет это быстрый. Некоторые более высокие и более новые делают, но это не стандартно (пока ...).

Что касается замечания «игнорировать десятилетия технологий», мне все еще за двадцать, поэтому, когда я экстраполирую задом наперед, я в основном повторяю то, что говорили мне более старые и более опытные программисты. Очевидно, что это будет оспариваться на сайте, как это, но это стоит рассмотреть.


4
« C # для чего-нибудь Windows » - О, это такая ошибка. И вы даже приводите пример. Единство. AFAIK Это не написано, он предоставляет C # API, потому что язык хорошо адаптируется. Это действительно хорошо продумано. И мне больше нравится c ++, но следует отдать должное, где это необходимо. Может быть, вы смешали C # с .NET? Они тусуются вместе довольно часто.
luk32

2
«Даже Unity - это не все C #, огромные куски - это C ++» И? Игры в Unity часто используют C # и существуют уже довольно давно. Предположение о том, что C # «только недавно достиг скорости», либо нуждается в большем количестве контекста, либо рискует быть слепым к технологиям этого десятилетия.
NPSF3000

2
Почти каждая большая игра была написана на языке движка, который она использовала: объем работы, который потребовался бы для дублирования, был настолько велик, что никакие другие технические соображения даже не стоили принимать во внимание. Рендеринг действительно дорог, но в настоящее время все написано в шейдерах, а язык логического цикла не имеет значения.
Питер Тейлор,

2
C # всегда был скомпилирован JIT (в отличие от Java, где ваш комментарий верен), и он был вполне способен на очень близкие скорости выполнения к C ++ с самого начала, если вы знали, что делаете. Это 2003 год - не то, что я бы посчитал недавним. Необработанная скорость не является главной проблемой для игр (особенно с программируемыми шейдерами на графическом процессоре), есть и другие вещи, которые делали такие языки, как C #, более или менее популярными в разы. Двумя основными проблемами являются API (которые в значительной степени ориентированы на C, а взаимодействие может быть дорогим) и GC (в основном из-за проблем с задержкой, а не из-за необработанной пропускной способности).
Луаан

1
@gbjbaanb Дело не только в том, что процессоры работают быстрее - важно, что у C ++ и C были десятилетия, чтобы усовершенствовать свои компиляторы и среду выполнения, в то время как Java начинала практически с нуля (будучи спроектированной в первую очередь как многоплатформенная платформа). По мере улучшения ВМ (например, переход от интерпретатора к JIT-компилятору, улучшение GC ...) росла и производительность Java-приложений. Большая часть преимуществ C / C ++ по-прежнему заключается в подходе «будем надеяться, что ничего не сломается» - избегая множества проверок, которые считаются «ненужными». Но это все еще огромная проблема с памятью - на самом деле, улучшения в использовании процессора часто означали худшую производительность памяти :)
Luaan

13

Забавно, что вы утверждаете, что C небезопасен, потому что «у него есть указатели». Верно обратное: Java и C # имеют практически только указатели (для не нативных типов). Наиболее распространенной ошибкой в ​​Java, вероятно, является исключение нулевого указателя (см. Https://www.infoq.com/presentations/Null-References-The-Billion-Dollar-Mistake-Tony-Hoare ). Второй наиболее распространенной ошибкой, вероятно, являются скрытые ссылки на неиспользуемые объекты (например, закрытые диалоги не удаляются), которые поэтому не могут быть освобождены, что приводит к длительным программам с постоянно растущим отпечатком памяти.

Существует два основных механизма, которые делают C # и Java более безопасными и безопасными двумя различными способами:

  • Сборка мусора снижает вероятность того, что программа попытается получить доступ к удаленным объектам. Это снижает вероятность неожиданного завершения программы. В отличие от C, Java и C # по умолчанию распределяют не собственные данные динамически. Это делает логику программы на самом деле более сложной, но встроенная сборка мусора - за плату - берет на себя сложную часть.

Последние умные указатели C ++ облегчают эту работу для программистов.

  • Java и C # компилируются в промежуточный код, который интерпретируется / выполняется сложным временем выполнения. Это добавляет уровень безопасности, поскольку во время выполнения могут обнаруживаться незаконные действия программы. Даже если программа написана ненадежно (что возможно на обоих языках), теоретически соответствующее время выполнения предотвращает «взлом» системы.
    Время выполнения не защищает, например, от попыток переполнения буфера, но теоретически не позволяет использовать такие программы. В отличие от C и C ++, программист должен надежно кодировать, чтобы предотвратить эксплойты. Это обычно не достигается сразу, но нуждается в обзорах и итерациях.

Стоит отметить, однако, что сложное время выполнения также является угрозой безопасности. Мне кажется, что Oracle обновляет JVM каждые пару недель из-за недавно обнаруженных проблем безопасности. Конечно, гораздо сложнее проверить JVM, чем отдельную программу.

Поэтому безопасность тщательно продуманного времени выполнения неоднозначна и в некоторой степени обманчива: ваша средняя программа на C может быть сделана с помощью проверок и итераций достаточно безопасной. Ваша обычная Java-программа настолько безопасна, насколько JVM; то есть не совсем. Никогда.

Статья, на gets()которую вы ссылаетесь, отражает исторические библиотечные решения, которые сегодня будут приняты по-другому, а не основной язык.


3
Я думаю, что смысл оригинального автора в том, что в C вы можете предпринять действия без контроля над этими указателями. В java вы сразу получаете хорошее исключение - в C вы можете не осознавать, что читаете неверное местоположение, пока состояние вашего приложения не будет повреждено.
Сэм Дюфель

1
Кроме того, stackoverflow.com/questions/57483/… - точнее было бы сказать, что в java есть «практически только ссылки».
Сэм Дюфель

4
Я видел все виды интересных ошибок в результате попыток избежать явных указателей. Обычно основной проблемой является путаница между копией и ссылкой. В Си, если я передам вам указатель на что-то, вы знаете, что его изменение повлияет на оригинал. Некоторые попытки избежать указателей скрывают это различие, приводя к лабиринту глубоких копий, мелких копий и общей путанице.
Арли Стивенс

Утверждение, что Oracle JVM отстой (с точки зрения кровоизлияния уязвимостей в области безопасности) и, следовательно, время выполнения управляемых языков в целом создает больше проблем безопасности, чем использование управляемого языка, - все равно, что сказать, что Adobe Flash ужасен как источник небезопасности, и программа, которая действительно ли воспроизведение видео и анимации с веб-сайта должно быть смехотворно небезопасным. Не все среды выполнения Java почти так же плохи, как мерзость JVM Oracle / Sun 1990-х годов, и не все управляемые языки являются Java. (Ну, очевидно.)
основном сообщается

@halfinformed Хорошо; Я говорил, что программа безопасна настолько же, насколько и ее среда выполнения, и что «ваша средняя» программа (читай: small-ish) с усилием может быть сделана более безопасной, чем любая большая среда выполнения, такая как интерпретатор байт-кода. Это утверждение кажется неоспоримым. Является ли конкретная автономная программа или конкретная среда выполнения более или менее защищенной, чем другая, зависит от их соответствующей сложности и дизайна, качества кодирования и обслуживания. Например, я бы не сказал, что sendmail более безопасен, чем Oracle VM VM; но qmail может быть.
Питер А. Шнайдер

10

Поскольку «безопасность» стоит скорости, «безопасные» языки работают медленнее.

Вы спрашиваете, зачем использовать «опасный» язык, такой как C или C ++, кто-то напишет вам видеодрайвер или тому подобное на Python или Java и т. Д. И посмотрите, что вы думаете о «безопасности» :)

Если серьезно, то вы должны быть как можно ближе к основной памяти машины, чтобы иметь возможность манипулировать пикселями, регистрами и т. Д. ... Java или Python не могут сделать это с любым типом быстродействия, достаточным для производительности ... C и C ++ оба позволяют вам делать это с помощью указателей и тому подобного ...


20
В общем, это не правда, что безопасность стоит скорости . Самые безопасные из доступных языков выполняют большинство проверок во время компиляции. O'Caml, Ada, Haskell, Rust не сильно отстают от C по средней скорости выполнения. Что они обычно делают, так это значительные накладные расходы в размере программы, эффективности памяти, задержке и, очевидно, времени компиляции. И, да, они испытывают трудности с мелочами. Но это не проблема скорости.
оставлено около

6
Кроме того, C не делает то, что вы думаете, что делает. С - абстрактная машина . Это не дает вам прямой доступ ни к чему - это хорошо. Вы даже не можете взглянуть на современную сборку, чтобы увидеть, сколько C скрывает от вас - современная сборка (например, TASM) считалась бы языком высокого уровня еще при разработке C. Я был бы очень рад, если бы кто-то писал драйверы на «безопасном» языке, спасибо - это бы очень помогло избежать множества таких BSOD и зависаний, не говоря уже о дырах в безопасности :) И самое главное, есть системные языки, которые намного безопаснее чем C.
Luaan

3
@Wintermute Вы действительно хотите посмотреть Rust, прежде чем комментировать, что функции безопасности обязательно стоят быстрее. Черт, низкоуровневая система типов C фактически запрещает много очень полезных оптимизаций, которые в противном случае могли бы делать компиляторы (особенно если учесть, что практически ни одному крупному c-проекту не удается избежать, чтобы не нарушать строгое алиасинг где-либо ).
Во

7
@Wintermute Да, миф о том, что вы не можете сделать C / C ++ более безопасным, не увеличивая производительность, очень устойчив, поэтому я отношусь к этому довольно серьезно (есть некоторые области, где это, безусловно, верно [проверка границ]). Теперь, почему Rust не более распространен? История и сложность. Rust все еще относительно новый, и многие из крупнейших систем, написанных на C, существовали до того, как был изобретен Rust - вы не собираетесь переписывать миллион LOC на новом языке, даже если это было бы намного безопаснее. Также каждый программист и их собака знают C, Rust? Удачи в поиске достаточно людей.
Во

3
@ Voo Dogs делают C? ... не удивительно, что я видел столько плохого кода там ... j / k Точка зрения о Rust (я только что скачал и установил его, так что вы можете добавить еще один конверт) BTW в отношении чтобы Rust делал все правильно ... Я мог бы сделать то же самое увеличение для "D" :)
Wintermut3

9

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

В основном, почти все языки имеют интерфейс API для C.

Простой пример, попробуйте создать общее приложение для Linux / IOS / Android / Windows. Помимо всех имеющихся инструментов, мы создали библиотеку ядра на C, а затем изменили графический интерфейс для каждой среды, а именно:

  • IOS: ObjectiveC может использовать библиотеки C изначально
  • Android: Java + JNI
  • Linux / Windows / MacOS: с GTK / .Net вы можете использовать нативные библиотеки. Если вы используете Python, Perl, Ruby, у каждого из них есть собственные интерфейсы API. (Ява снова с JNI).

Мои два цента,


Одна из причин, по которой я люблю использовать, скажем, PHP, заключается в том, что почти все его библиотеки действительно написаны на C - к счастью, иначе PHP был бы невыносимо медленным :) PHP великолепен для написания неаккуратного кода без страха перед делать что-то «опасное» (и именно поэтому я склонен писать намного больше кода PHP, чем что-либо еще - мне нравится небрежный код!: D), но приятно знать, что под многими из этих вызовов функций есть хороший старый надежный Библиотеки C для повышения производительности ;-) Напротив, написание небрежного кода на C - это большое «нет-нет» ...
Гвинет Ллевелин,

7

Фундаментальная трудность с C состоит в том, что имя используется для описания ряда диалектов с идентичным синтаксисом, но очень различной семантикой. Некоторые диалекты намного безопаснее других.

В C, изначально разработанном Деннисом Ритчи, операторы C обычно отображаются в машинные инструкции предсказуемым образом. Поскольку C мог работать на процессорах, которые вели себя по-разному, когда происходили такие вещи, как подписанное арифметическое переполнение, программист, который не знал, как поведет себя машина в случае арифметического переполнения, не знал бы, какой код C, работающий на этой машине, тоже будет себя вести, но если машина, как было известно, ведет себя определенным образом (например, обход без компиляции с двумя дополнительными компонентами), то реализации на этой машине обычно делают то же самое. Одна из причин, по которой С приобрел репутацию быстрой, заключается в том, что в тех случаях, когда программисты знали, что естественное поведение платформы в сценариях с граничными случаями соответствует их потребностям, программисту или компилятору не нужно было писать код для генерации таких сценариев. ,

К сожалению, авторы компиляторов придерживаются мнения, что, поскольку Стандарт не предъявляет никаких требований к тому, что реализации должны делать в таких случаях (слабость, которая должна была обеспечить аппаратные реализации, которые могут вести себя непредсказуемо), компиляторы должны свободно генерировать код, который отрицает законы времени и причинности.

Рассмотрим что-то вроде:

int hey(int x)
{
   printf("%d", x);
   return x*10000;
}
void wow(int x)
{
  if (x < 1000000)
    printf("QUACK!");
  hey(x);    
}

Гиперсовременная (но модная) теория компилятора предполагает, что компилятор должен выводить «QUACK!» безусловно, поскольку в любом случае, когда условие было ложным, программа в конечном итоге вызывала неопределенное поведение, выполняющее умножение, результат которого все равно будет игнорироваться. Поскольку стандарт позволяет компилятору делать все, что ему нравится, в таком случае он позволяет компилятору выводить «QUACK!».

В то время как C раньше был безопаснее ассемблера, при использовании гиперсовременных компиляторов верно обратное. В языке ассемблера целочисленное переполнение может привести к тому, что вычисления приведут к бессмысленному результату, но на большинстве платформ это будет иметь степень его влияния. Если результаты в конечном итоге будут проигнорированы, переполнение не будет иметь значения. В гиперсовременном C, однако, даже то, что обычно было бы «доброкачественными» формами неопределенного поведения (такими как целочисленное переполнение в вычислении, которое в конечном итоге игнорируется), может вызвать произвольное выполнение программы.


1
даже в сверхсовременном компиляторе C не проверяет границы массивов. если это так, это не будет совместимо с определением языка. я иногда использую этот факт для создания массивов с дополнительным указателем на середину массива, чтобы иметь отрицательные индексы.
Роберт Бристоу-Джонсон

1
Я хотел бы видеть свидетельство того, что ваш пример производит "КВАК!" безусловно. x, безусловно, может быть больше 1000000 в точке сравнения, и последующая оценка, которая может привести к переполнению, не предотвращает это. Более того, если у вас включено встраивание, которое позволяет убирать переполнение, ваш аргумент об неявных ограничениях диапазона не выполняется.
Грэм

2
@ robertbristow-johnson: На самом деле стандарт прямо говорит, что, например int arr[5][[5], попытка доступа arr[0][5]приведет к неопределенному поведению. Такое правило делает возможным для компилятора, которому дано что-то вроде arr[1][0]=3; arr[0][i]=6; arr[1][0]++;вывода, которое arr[1][0]будет равно 4, без учета значения i.
суперкат

2
@ robertbristow-johnson: Даже если компилятор распределяет массивы внутри структуры последовательно без пробелов, это не гарантирует, что индексация одного из массивов гарантированно повлияет на другой. Смотрите godbolt.org/g/Avt3KW для примера того, как gcc будет обрабатывать такой код.
Суперкат

1
@ robertbristow-johnson: Я прокомментировал сборку, чтобы объяснить, что она делает. Компилятор видит, что код сохраняет 1 в s-> arr2 [0], а затем увеличивает s-> arr2 [0], поэтому gcc объединяет эти две операции, позволяя коду просто сохранить значение 2, не учитывая вероятность того, что промежуточная запись to s-> arr1 [i] может повлиять на значение s-> arr1 [0] (поскольку, согласно Стандарту, это не может).
суперкат

5

Исторические причины. Я не часто пишу новый код, в основном я поддерживаю и расширяю старые вещи, которые работают уже десятилетия. Я просто счастлив, что это С, а не Фортран.

Я могу раздражаться, когда какой-то студент говорит: «Но с какой стати ты делаешь этот ужасный Х, когда ты можешь делать Y?». Ну, Х - это моя работа, и она очень хорошо оплачивает счета. Иногда я делал Y, и это было весело, но большинство из нас делают X.


5

Что такое "опасно"?

Утверждение, что C «опасен», является частым предметом разговора в языковых войнах пламени (чаще всего по сравнению с Java). Тем не менее, доказательства этого требования неясны.

C - это язык с определенным набором функций. Некоторые из этих функций могут допускать определенные типы ошибок, которые не допускаются другими типами языков (обычно выделяется риск управления памятью в C). Однако это не то же самое, что аргумент, что C более опасен, чем другие языки в целом . Я не знаю никого, кто бы предоставил убедительные доказательства по этому вопросу.

Кроме того, «опасный» зависит от контекста: что вы пытаетесь сделать, и какие риски вы беспокоитесь?

Во многих контекстах я бы посчитал C более «опасным», чем язык высокого уровня, потому что он требует от вас больше ручной реализации основных функций, увеличивая риск ошибок. Например, выполнять некоторую базовую обработку текста или разработку веб-сайта на C обычно глупо, потому что другие языки имеют функции, которые делают это намного проще.

Тем не менее, C и C ++ широко используются для критически важных систем, поскольку меньший язык с более прямым контролем над hardward считается «более безопасным» в этом контексте. Из очень хорошего ответа переполнения стека :

Хотя C и C ++ не были специально разработаны для этого типа приложений, они широко используются для встроенного и критически важного для безопасности программного обеспечения по нескольким причинам. Основные свойства заметки: контроль над управлением памятью (что позволяет избежать необходимости, например, сбора мусора), простые, хорошо отлаженные библиотеки времени выполнения ядра и поддержка зрелых инструментов. Многие из используемых в настоящее время цепочек встроенных средств разработки были впервые разработаны в 1980-х и 1990-х годах, когда это была текущая технология, и исходили из культуры Unix, которая была распространена в то время, поэтому эти инструменты остаются популярными для такого рода работ.

Хотя код ручного управления памятью необходимо тщательно проверять во избежание ошибок, он позволяет в определенной степени контролировать время отклика приложения, которое недоступно для языков, зависящих от сборки мусора. Базовые библиотеки времени выполнения языков C и C ++ относительно просты, зрелы и понятны, поэтому они являются одними из самых стабильных платформ.


2
Я бы сказал, что гиперсовременный C также более опасен, чем язык ассемблера или подлинные низкоуровневые диалекты C, которые постоянно ведут себя так, как будто они последовательно переводят операции C в операции машинного кода, без учета крайних случаев, когда операции естественного машинного кода будут имеют определенное поведение, но стандарт C не налагает никаких требований. Гиперсовременный подход, в котором целочисленное переполнение может свести на нет правила времени и причинности, кажется гораздо менее поддающимся генерации безопасного кода.
суперкат

5

Чтобы добавить к существующим ответам, все хорошо, что вы выберете Python или PHP для своего проекта из-за их относительной безопасности. Но кто-то должен реализовать эти языки, и когда они это сделают, они, вероятно, собираются сделать это на C. (Или, ну, что-то вроде этого).

Вот почему люди используют C - для создания менее опасных инструментов, которые вы хотите использовать.


2

Позвольте мне перефразировать ваш вопрос:

Я рассматриваю возможность обучения [инструмент].

Но почему люди используют [инструмент] (или [связанный инструмент]), если [их] можно использовать «опасно»?

Опасно использовать любой интересный инструмент, в том числе языки программирования. Вы узнаете больше, чтобы сделать больше (и чтобы при использовании инструмента создавалась меньшая опасность). В частности, вы изучаете инструмент так, чтобы вы могли делать то, для чего этот инструмент хорош (и, возможно, узнавать, когда этот инструмент является лучшим инструментом из известных вам инструментов).

Например, если вам нужно вставить цилиндрическое отверстие диаметром 6 мм и глубиной 5 см в блок из дерева, сверло будет гораздо лучшим инструментом, чем анализатор LALR. Если вы знаете, каковы эти два инструмента, вы знаете, какой инструмент является правильным. Если вы уже знаете, как использовать дрель, вуаля!

С это просто еще один инструмент. Это лучше для некоторых задач, чем для других. Другие ответы здесь обращаются к этому. Если вы выучите некоторую C, вы поймете, когда это правильный инструмент, а когда нет.


Этот ответ таков, почему вопросы выбрасываются как «в первую очередь основанные на мнении». Не говорите, что у С есть свои преимущества, говорите, что они есть!
reinierpost

1

Я рассматриваю возможность изучения C

Нет особой причины не изучать C, но я бы предложил C ++. Он предлагает большую часть того, что делает C (поскольку C ++ - это супер-набор C), с большим количеством «дополнений». Изучение C до C ++ не является необходимым - они фактически являются отдельными языками.

Другими словами, если бы C был набором деревообрабатывающих инструментов, он, вероятно, был бы:

  • молоток
  • ногти
  • ручная пила
  • ручная дрель
  • блок шлифовальный
  • долото (возможно)

Вы можете создать что - нибудь с этими инструментами - но ничего хорошего потенциально требует много времени и мастерства.

C ++ - это набор мощных инструментов в вашем местном хозяйственном магазине.

Если вы придерживаетесь базовых языковых возможностей, C ++ имеет относительно небольшую дополнительную кривую обучения.

Но почему люди используют C (или C ++), если его можно использовать «опасно»?

Потому что некоторые люди не хотят мебель от ИКЕА. знак равно

Если серьезно, то, хотя многие языки, которые «выше» C или C ++, могут иметь вещи, которые делают их (потенциально) «более простыми» в использовании в определенных аспектах, это не всегда хорошо. Если вам не нравится то, как что-то делается, или функция не предоставляется, скорее всего, вы ничего не можете с этим поделать. С другой стороны, C и C ++ предоставляют достаточно «низкоуровневых» языковых возможностей (включая указатели), чтобы вы могли получить доступ ко многим вещам довольно напрямую (особенно с аппаратной или операционной системой) или создать их самостоятельно, что может быть невозможно в других случаях. языки как реализовано.

В частности, C имеет следующий набор функций, которые делают его желательным для многих программистов:

  • Скорость - из-за относительной простоты и оптимизации компиляции в течение многих лет, она изначально очень быстрая. Кроме того, многие люди при использовании языка нашли множество ярлыков для конкретных целей, что делает его потенциально еще быстрее.
  • Размер. По тем же причинам, которые указаны для скорости, программы на Си могут быть очень маленькими (как с точки зрения размера исполняемого файла, так и использования памяти), что желательно для сред с ограниченным объемом памяти (т. Е. Встроенных или мобильных).
  • Совместимость - C существует уже давно, и у каждого есть инструменты и библиотеки для него. Сам язык также не требователен - он ожидает, что процессор будет выполнять инструкции, а память - для хранения информации, и это все.

    Кроме того, существует нечто, известное как двоичный интерфейс приложения (ABI) . Короче говоря, это способ взаимодействия программ на уровне машинного кода, который может иметь преимущества перед интерфейсом прикладного программирования (API) . В то время как другие языки, такие как C ++, могут иметь ABI, обычно они менее единообразны (согласованы), чем C, поэтому C делает хороший базовый язык, когда вы хотите по какой-то причине использовать ABI для взаимодействия с другой программой.

Почему программисты не просто используют Java, Python или другой скомпилированный язык, такой как Visual Basic?

Эффективность (и иногда схемы управления памятью, которые не могут быть реализованы без относительно прямого доступа к памяти).

Прямой доступ к памяти с помощью указателей вводит много аккуратных (обычно быстрых) трюков, когда вы можете положить свои грязные лапы на маленькие и нули прямо в свои ячейки памяти и не нужно ждать, пока этот учитель раздаст игрушки во время игры, затем выкопайте их снова.

Короче говоря, добавление материала потенциально создает задержку или иным образом создает нежелательную сложность.

Что касается скриптовых языков и тому подобного, вы должны усердно работать, чтобы получить языки, требующие, чтобы вторичные программы работали так же эффективно, как изначально C (или любой скомпилированный язык). Добавление интерпретатора «на лету» по своей сути вводит возможность снижения скорости выполнения и увеличения использования памяти, поскольку вы добавляете в микшер еще одну программу. Эффективность ваших программ зависит как от эффективности этой вторичной программы, так и от того, насколько хорошо (плохо =) вы написали исходный программный код. Не говоря уже о том, что ваша программа часто полностью зависит от второй программы. Эта вторая программа по какой-то причине не существует в конкретной системе? Код не идет.

Фактически, введение чего-то «лишнего» потенциально замедляет или усложняет ваш код. В языках «без страшных указателей» вы всегда ждете, чтобы другие кусочки кода очистились позади вас, или иным образом выясните «безопасные» способы сделать что-то - потому что ваша программа все еще выполняет те же операции доступа к памяти, что и с указатели. Вы просто не тот, кто с этим справляется (так что вы не можете его обдумать, genius = P).

Под опасным я имею в виду указатели и другие подобные вещи. [...] Как и вопрос переполнения стека. Почему функция gets настолько опасна, что ее не следует использовать?

Согласно принятому ответу:

«Он оставался официальной частью языка до стандарта ISO C 1999 года, но он был официально удален стандартом 2011 года. Большинство реализаций C все еще поддерживают его, но по крайней мере gcc выдает предупреждение для любого кода, который его использует».

Представление о том, что, поскольку что-то может быть сделано на языке, это должно быть сделано, глупо. У языков есть недостатки, которые исправляются. По соображениям совместимости со старым кодом эта конструкция все еще может использоваться. Но нет ничего (вероятно), заставляющего программиста использовать get (), и, фактически, эта команда была по существу заменена более безопасными альтернативами.

Более того, проблема с get () сама по себе не является проблемой указателя . Это проблема с командой, которая не обязательно знает, как безопасно использовать память. В абстрактном смысле, это все проблемы с указателями - чтение и запись вещей, которые вы не должны делать. Это не проблема с указателями; это проблема с реализацией указателя.

Чтобы уточнить, указатели не опасны, пока вы случайно не получите доступ к области памяти, которую вы не собирались. И даже тогда это не гарантирует, что ваш компьютер тает или взрывается. В большинстве случаев ваша программа просто перестанет функционировать (правильно).

Тем не менее, поскольку указатели предоставляют доступ к областям памяти и поскольку данные и исполняемый код существуют в памяти вместе, существует реальная опасность случайного повреждения, что вы хотите правильно управлять памятью.

В связи с этим, поскольку в действительности операции прямого прямого доступа к памяти часто дают меньше преимуществ, чем они могли бы получить много лет назад, даже языки без сбора мусора, такие как C ++, ввели такие вещи, как интеллектуальные указатели, чтобы помочь преодолеть разрыв между эффективностью и безопасностью памяти.

Таким образом, существует очень мало причин бояться указателя, если он используется безопасно. Просто возьмите намек на версию Стива "Охотник за крокодилами" Ирвина из Саут-Парка - не торопитесь засунуть большой палец в дырки крокодилов .


2
Я не согласен с предложением изучать C ++ вместо C. Написание хорошего C ++ сложнее, чем написание хорошего C, а чтение C ++ намного сложнее, чем чтение C. Таким образом, кривая изучения C ++ намного круче. «C ++ - это супер-набор C» Это более или менее похоже на то, что сапоги - это супер-набор тапочек. У них разные преимущества и использование, и у каждого есть особенности, которых нет у другого.
Мартынкунев

«Написание хорошего C ++ сложнее, чем написание хорошего C» - абсолютно. =) «[R] изучать C ++ намного сложнее, чем читать C» - любое продвинутое программирование, вероятно, неотличимо от магии ;-) Мои два цента в том, что это гораздо больше зависит от программиста, чем от языка, хотя C ++ не делает ничего, чтобы помочь себе в этой категории. «Таким образом, кривая изучения C ++ намного круче». - В конце концов, да. В краткосрочной перспективе менее того (мое мнение). Как ни странно, большинство базовых языковых курсов в C и C ++, вероятно, охватывают примерно одни и те же общие типы материалов, за исключением классов для C ++.
Анаксунаман

2
«У них разные преимущества и использование, и у каждого есть особенности, которых нет у другого». - Как уже упоминалось, «нет особых причин не изучать C [.]» C - хороший язык, и я придерживаюсь этого. Если это подходит OP или кому-либо еще, я полностью поддерживаю изучение этого. =)
Анаксунаман

Обучение C научит вас, как работает машина (не полностью, но все же на шаг ближе к металлу). Это очень хорошая причина для изучения этого.
Agent_L

1

Как всегда, язык программирования является лишь следствием решения проблем. На самом деле вы должны выучить не только C, но и много разных языков (и других способов программирования компьютера, будь то GUI-инструменты или интерпретаторы команд), чтобы иметь приличный инструментарий для решения проблем.

Иногда вы обнаружите, что проблема хорошо подходит для чего-то, что включено в библиотеки Java по умолчанию, в таком случае вы можете выбрать Java, чтобы использовать это. В других случаях может случиться так, что вам нужно сделать что-то в Windows, что намного проще во время выполнения .NET, поэтому вы можете использовать C # или VB. Там может быть графический инструмент или командный скрипт, который решит вашу проблему, тогда вы можете использовать их. Возможно, вам нужно написать приложение с графическим интерфейсом на нескольких платформах, Java может быть вариантом, учитывая включенные библиотеки в JDK, но с другой стороны, на одной целевой платформе может отсутствовать JRE, поэтому, возможно, вы вместо этого выберете C и SDL (или аналог).

C занимает важное место в этом наборе инструментов, так как он общий, небольшой и быстрый, а также компилируется в машинный код. Он также поддерживается на каждой платформе под солнцем (однако не без перекомпиляции).

В итоге вы должны выучить как можно больше инструментов, языков и парадигм.

Пожалуйста, отойдите от мышления: «Я программист X» (X = C, C ++, Java и т. Д.)

Просто используйте «Я программист».

Программист решает проблемы и разрабатывает алгоритмы, инструктируя машины выполнять рабочую нагрузку. Конец истории. Это не имеет отношения к языку. Ваш самый важный навык - это решение проблем и логическая разбивка структурированных проблем, языковой навык / выбор ВСЕГДА вторичен и / или является следствием характера проблемы.

Интересный путь, если вы заинтересованы в C, - это расширить свой набор навыков с помощью Go. Go - действительно улучшенный C, со сборщиком мусора и интерфейсами, а также с хорошей встроенной потоковой моделью / каналами, которые также приносят многие преимущества C (такие как арифметика указателей и компиляция в машинный код).


0

Это зависит от того, что вы собираетесь с этим делать. C был разработан для замены языка ассемблера и является языком высокого уровня, наиболее близким к машинному языку. Таким образом, он имеет низкие накладные расходы по размеру и производительности и подходит для системного программирования и других задач, которые требуют небольшой площади и приближаются к базовому оборудованию.


0

Когда вы работаете на уровне битов и байтов памяти, как сырой однородный сбор данных, что часто требуется для эффективной реализации наиболее эффективных распределителей и структур данных, безопасность не требуется. Безопасность - это преимущественно концепция, связанная с типами данных, а распределитель памяти не работает с типами данных. Он работает с битами и байтами для объединения с теми же битами и байтами, потенциально представляющими один тип данных один момент, а другой позже.

Не имеет значения, используете ли вы C ++ в этом случае. Вы по-прежнему будете разбрасывать static_castsвесь код для приведения из void*указателей и все еще работать с битами и байтами и просто иметь дело с большим количеством хлопот, связанных с уважением системы типов в этом контексте, чем в C, который имеет гораздо более простую систему типов, где вы свободны на memcpyкусочки и байты вокруг, не беспокоясь о бульдозере над системой типов.

На самом деле, в таких низкоуровневых контекстах битов и байтов часто труднее работать в C ++, в целом более безопасном языке, без написания даже более опасного кода, чем в C, поскольку вы могли бы разбираться с системой типов C ++ и делать такие вещи, как перезаписывать vptrs и не вызывать конструкторы и деструкторы копирования в подходящее время. Если вы уделите должное время уважению этих типов и используете размещение новых и вызовете dtors вручную и т. Д., То вы попадаете в мир обработки исключений в контексте слишком низкого уровня, чтобы RAII был практичным, и достигали исключения. безопасность в таком низкоуровневом контексте очень трудна (вы должны притворяться, будто любая функция может выбросить и поймать все возможности и откатить любые побочные эффекты как неделимую транзакцию, как будто ничего не произошло). Код C часто может

И было бы невозможно реализовать такие распределители на языках, которые не позволяют вам становиться «опасными» здесь; вам придется опираться на любые предоставляемые ими распределители (реализованные, скорее всего, на C или C ++) и надеяться, что этого достаточно для ваших целей. И почти всегда есть более эффективные, но менее общие распределители и структуры данных, подходящие для ваших конкретных целей, но гораздо более узко применимые, поскольку они специально предназначены для ваших целей.

Большинству людей не нужны подобные C или C ++, поскольку они могут просто вызывать код, изначально реализованный на C или C ++, или, возможно, даже сборку, уже реализованную для них. Многие могли бы извлечь выгоду из инноваций на высоком уровне, например, связать воедино программу для работы с изображениями, которая просто использует библиотеки существующих функций обработки изображений, уже реализованных в C, где они не так много делают для инноваций на самом низком уровне с циклическим просмотром отдельных пикселей, но, возможно, предлагая очень дружественный пользовательский интерфейс и рабочий процесс, никогда не видел раньше. В этом случае, если целью программного обеспечения является просто выполнение высокоуровневых вызовов в низкоуровневые библиотеки ( «обработайте все это изображение для меня, а не для каждого пикселя, сделайте что-нибудь» ), то это может быть преждевременной оптимизацией даже попытаться начать писать такое приложение на C.

Но если вы делаете что-то новое на низком уровне, где он помогает получить доступ к данным на низком уровне, например, совершенно новый фильтр изображений, которого раньше не было, и который достаточно быстр для работы с HD-видео в реальном времени, тогда вам, как правило, нужно получить немного опасно

Легко принять это как должное. Я помню пост в Фейсбуке, где кто-то указывал, как выполнимо создать 3D-видеоигру с Python, имея в виду, что низкоуровневые языки устаревают, и это была, безусловно, приличная игра. Но Python делал высокоуровневые вызовы в библиотеки, реализованные на C, чтобы выполнить всю тяжелую работу. Вы не можете сделать Unreal Engine 4, просто делая высокоуровневые вызовы в существующие библиотеки. Unreal Engine 4 естьбиблиотека. Он делал все, что никогда не существовало в других библиотеках и механизмах, от освещения до даже его узловой системы разработки чертежей и того, как он может компилировать и запускать код на лету. Если вы хотите вводить новшества на низком уровне движка / ядра / ядра, то вы должны перейти на низкий уровень. Если бы все разработчики игр переключились на безопасные языки высокого уровня, не было бы Unreal Engine 5, 6 или 7. Вероятно, люди будут все еще использовать Unreal Engine 4 десятилетия спустя, потому что вы не можете вводить новшества на уровне, необходимом для достижения с двигателем следующего поколения, просто делая высокоуровневые звонки на старый.

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.