С чего стоит начинать изучение программирования?

С чего стоит начинать изучение программирования?

Этот вопрос имеет огромную историю и аудиторию, и такую же неоднозначность (где много людей — там много мнений).

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

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

К тому же, сейчас в системе образования, в частности в IT, сложилась совершенно идиотическая ситуация: вместо того чтобы преподавать то, что действительно нужно, детям, им преподают «то, что знают» преподаватели. В результате вместо простых вещей типа Scratch, Small basic, Pascal, SketchUp и т.п. детям пихают Java, C++, Python, Blender…

Скажите, а вы серьёзно думаете, что начинать учиться ездить нужно на тяжелом магистральном грузовике с прицепом, а не на велосипеде или самокате, или, может быть, пилотов надо начинать обучать не на легких «Цесснах», АНах» и «ЯКах», а сразу на 747-х «Боингах» и 380-х «Аирбасах»? Интересно, как бы вам понравилось лететь куда-нибудь с таким вот пилотом?… Может быть лучше стоит этим «доморощеным» преподавателям самим пойти поучиться сначала? А чиновникам, утверждающим эти бредовые программы — хоть раз в жизни задуматься над тем, что они делают, а не только над тем, сколько они с этого поимеют? 

Во-первых, изучать программирование надо… не с языка, а с основ, в которые входят: основы алгоритмов, основы данных, основы устройства вычислительных систем и т.п. Это — если учащийся — достаточно взрослый и уже понимает, что и зачем он изучает. А если мы имеем дело с ребёнком, то начинать надо с программистских игрушек типа системы визуального программирования Scratch, которая имеет большую историю, прекрасно локализована, имеет онлайн и офлайн среды разработки, хорошо документирована и поддерживается большим сообществом во всём мире. В принципе, на Scratch можно создавать довольно серьёзные проекты, однако это не слишком удобно — именно потому что это учебная система визуального, а не текстового программирования.

После того как мы наигрались в Scratch и/или немного разобрались с основами информационных технологий, можно начинать пробовать программировать на каком-нибудь простом и понятном (читаемом и понимаемом) текстовом языке программирования. Таких языков, к сожалению, в настоящий момент практически нет: почти все (99,9%) текстовые языки программирования — английские, а следовательно — нечитаемые и, следовательно, непонимаемые для русскоязычных учащихся.

Однако, русскоязычное сообщество с упорством, достойным лучшего применения, демонстрирует определённое единодушие в вопросе «Какой язык программирования для вас был первым?»

Второй вопрос, который обычно не задаётся ни в коем случае — это: «А почему именно этот язык стал для вас первым?» Вот тут-то и кроется иситинная суть этого вопроса! И ответ, как правило чрезвычайно стандартен: «Так получилось, потому что язык программирования выбирался не профессиональным педагогом, а неким лицом, которому этот процесс доверили: чиновником, администратором, менеджером…» А иногда — и просто слепым случаем.

Обратите внимание, есть даже люди, «утверждающие», что совсем неплохо начинать изучение программирования с языка Ассемблера (по крайней мере, они именно с него и начинали)…

Просто для примера — стандартная программка «Hello World!» на Ассемблере:

         .model tiny               ; Модель памяти, используемая для .COM
         .code                        ; Начало сегмента кода
         org  100h                 ; Начальное значение счетчика - 100h
start:   mov  ah, 9             ; Номер функции DOS - в AH
         mov  dx, offset message   ; Адрес строки - в DX
         int  21h                    ; Вызов системной функции DOS
         mov  ax,4C00h
         int  21h                    ; Завершение программы
message  db   "Hello World!", 0Dh, 0Ah, '$'     ; Строка для вывода
         end  start                ; Конец программы

Не правда ли, всё очень «просто» и «понятно» (особенно, если убрать все комментарии, хотя и с ними — всё очень «занимательно») — как раз «идеально» для начального обучения программированию? 🙂

Хорошо, но это Ассемблер, а как же Python, уверенно удерживающий тут первое место? Да точно так же как идея плоской Земли — хорошо распиаренная и проплаченная бредятина. Единственное отличие Python в том, что он якобы «прост», только вот простота его хороша не для обучения, а для лентяев… 🙁

Да, Python — популярный язык программирования, популярность которого обусловлена… исключительно финансовыми вливаниями и PR-акциями Google. Создатель Python работал в Google с 2005 по 2012 год. Таких языков, как Go и Dart, тогда еще не было, или, по крайней мере, они не были широко известны, а с учетом того, что C# от Microsoft набирал популярность, в Google приняли решение, что им непременно нужен «свой собственный» язык (прямо коты Матроскины какие-то!). По сути, можно было бы использовать, например, Java, но тогда бы Google не миновали очередных юридических проблем с Oracle. И тогда боссы компании (пусти козлов в огород!) выбрали Python и начали его раскручивать.

Одним из самых неприятных последствий этой раскрутки явилось внедрение Python в качестве основного школьного учебного языка программирования. Конечно, после ШАЯП и его аналогов:

алг Сумм (арг цел n, рез цел S)
   дано | n > 0
   надо | S = 1*1 + 2*2 + 3*3 + … + n*n
нач цел i
|  ввод n; S:=0
|  нц для i от 1 до n
|  |  S := S + i * i
|  кц
|  вывод "S = ", S
кон

код на которых напоминает панель управления самоходной гаубицей, программа на Python кажется на первый взгляд гораздо более «понятной»:

>>> def deco(func):
...     def inner():
...         print('running inner()')
...     return inner
…
>>> @deco
... def target():
...     print('running target()')
>>> target()
running inner()
>>> target
<function deco.<locals>.inner at 0.10063b598>

В принципе, какая разница: непонятные русские сокращения или непонятные английские слова? И то — невоспринимаемо, и это — точно так же нечитаемо…

По сути дела в процессе обучения программированию Python «хорош» — для того чтобы сначала расслабить учащихся на примитивных задачах (под девизом:  просто»программирование — это просто!»), а затем запутать их — как только возникнут задачи более сложные, и в итоге — отбить у них всякое желание программировать. В итоге это приводит к тому, что  для них будет практически невозможным изучение нормальных языков программирования: у них совершенно другая логика и форма подачи информации в тексте программы. Можно также посмотреть вот эту статью о недостатках Python или статью о том, почему будущее не за ним.

Разумеется, для уже сформировавшегося программиста, который владеет основами текстового программирования на нормальных языках программирования, изучить ещё и Python — не составляет особого труда. Но мне не встречалось ни одного такого программиста, который (хорошо зная Си-подобные языки программирования и т.п.) утверждал бы, что Python — гораздо лучше их. В чём-то проще и где-то немного удобнее — да, но однозначно, лучше — нет.

Теперь перейдём к группе принципиально учебных языков программирования: Basic (классический) и Pascal. Здесь есть только одна проблема: в настоящее время эти языки безнадёжно устарели и практически не развиваются и не поддерживаются. К тому же, переход от них к какому-либо актуальному современному языку программирования будет так же сложен, как и переход от Scratch к C#. В своё время, лет 20-30 назад многие начинали изучение программирования с Basic или Pascal или такого же простого Fortran. Это безусловно, очень хороший опыт, на котором, однако, не стоило застревать надолго. Да, после Basic и Pascal язык C казался сперва слегка сложным и непривычным. В настоящее время  начинать обучение полноценному текстовому программированию, на мой взгляд, целесообразнее всего именно с языка C.

Что у нас осталось? А осталась группа универсальных Си-подобных языков, которые вполне современны, популярны, активно развиваются (кстати, почти без активной раскрутки и финансовых вливаний) и вполне взаимно совместимы на уровне семантики. Всё потому, что построены они все на основе языка Си. Это:

  • Сам Си
  • С++
  • C#
  • Java
  • JavaScript
  • PHP

То есть, если вы знаете Си, вы сможете понять код, написанный на любом из этих языков. Только в этом списке их 6, а вообще их насчитывается более десятка, и всё это — не какие-то «просто похожие» языки из одной области, а принципиально различные языки для самых разных задач и областей применения, очень мощные, популярные и с большой историей.

Да, всё это принципиально английские языки программирования, но зато при не слишком высоком уровне знания английского они вполне читаемы.

Почему именно Cи в итоге оказывается в приоритете ?

  1. Наиболее широкие возможности самого языка — от низкого до высокого уровня
  2. Быстродействие компилируемого и хорошо оптимизируемого языка
  3. Си-подобный синтаксис, который встречается во многих других языках программирования
  4. Актуальность использования в настоящее время
  5. Навыки работы с памятью, указателями и другими системными элементами
  6. Разумная сложность, которую можно регулировать
  7. После него легче изучать подобные языки, такие как Java или C++

После изучения языка C можно начать знакомство с окружающими его низкоуровневым языком Assembler и высокоуровневым C++. Уже в дальнейшем можно познакомиться с Python или JavaScript, для того чтобы хотя бы примерно понимать их недостатки, преимущества и особенности. Также опытные разработчики посоветуют вам изучить хотя бы один функциональный язык программирования. К примеру, Haskell, Go или Лисп.

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

Как вы уже поняли, языков программирования — очень много, даже о самых популярных из них невозможно рассказать в одной статье. Но это и не нужно. Самое важное, что нужно помнить начинающему программисту — путь в разработчики не является простым, всё это довольно сложно. Если вы слышали какие-то истории быстрого успеха, что за 6 месяцев люди становятся «крутыми разработчиками», то это всегда связано с быстрым изучением основ WEB-разработки, т.к. там очень просто начать что-то делать и не требуется большого количества знаний. Но это путь кодера, а не полноценного инженера-программиста. Не спешите «быстро» научиться программировать — так как скорее всего в результате у вас получится совсем не то, к чему вы изначально стремились.

PS: Есть такой старый шуточный тест для выбора языка программирования. (Прошу не воспринимать его всерьёз!)

Вот ещё интересная статья на тему

Почему я всё ещё люблю C, но при этом терпеть не могу C++?

Почему я всё ещё люблю C, но при этом терпеть не могу C++?

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

Как это обычно бывает у C-программистов, язык C не был ни моим первым языком, ни языком, после которого я уже не изучал ничего другого. Но мне всё ещё нравится этот язык, и когда мне нужно писать программы — я выбираю именно его. Правда, в то же время, я стараюсь быть в курсе того, что происходит в мире современных (и не очень) языков программирования. Я слежу за тенденциями в этой сфере и пишу собственный хобби-проект, связанный с мультимедийными технологиями, на Rust. Почему же я до сих пор не поменял C на что-то более современное? И при чём тут C++?

Почему C — это не самый лучший язык программирования?

Сразу скажу то, что, пожалуй, и так все знают: нет такого понятия, как «самый лучший язык программирования». С каждым языком связан набор задач, для решения которых он подходит лучше всего. Например, хотя и можно заниматься трассировкой лучей в Excel, применяя VBA, лучше будет делать это с использованием более подходящего языка. Поэтому полезно знать об ограничениях языков программирования — чтобы не жаловаться на то, что веб-серверы не пишут на Fortran, и на то, что почти нигде Perl или C++ не используется в роли внутренних скриптовых языков. C может считаться не очень хорошим языком по причинам, которые я перечислю ниже (это — помимо того, что язык этот просто очень старый и того, что его нельзя назвать активно развивающимся языком, но это — дело вкуса).

В синтаксисе C имеются неоднозначные конструкции (например, символ * может играть роль обычного оператора умножения, может применяться в виде унарного оператора разыменования, или может использоваться при объявлении указателей; а радости работы с typedef достойны отдельной статьи).

Этот язык не является безопасным. Например — в C-программах довольно часто встречаются ошибки, связанные с обращением к элементам массивов, которые находятся за пределами границ массивов. В языке нет проверок на ошибки такого рода, производимых во время выполнения программы. А вот, например, в Borland Pascal, не говоря уже о более современных языках, такие проверки есть (это — плюс, даже если подобные возможности можно, пользуясь параметрами компиляции, отключить ради повышения производительности). А использование в языке указателей ещё сильнее усложняет задачу программиста по поддержанию кода в хорошем состоянии. И, кроме того, C имеет и некоторые другие неприятные особенности, вроде возможности вызова функции без объявления прототипа, в результате чего функции легко можно передать аргумент неправильного типа.

У C довольно-таки скромная стандартная библиотека. В некоторых других языках программирования могут даже иметься стандартные веб-серверы (или, как минимум, всё, что нужно для создания таких серверов), а в стандартной библиотеке C нет даже описаний контейнеров.

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

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

Например, если нужно получить значение элемента массива, имея два смещения, одно из которых может быть отрицательным числом, то при программировании на C можно воспользоваться такой конструкцией: arr[off1 + off2]. А при использовании Rust это уже будет arr[((off1 as isize) + off2) as usize]. C-циклы часто короче, чем идиоматичные механизмы Rust, использование которых предусматривает комбинирование итераторов (конечно, обычными циклами можно пользоваться и в Rust, но это не приветствуется линтером, который всегда рекомендует заменять их итераторами). И, аналогично, мощными инструментами являются memset() и memmove().

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

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

При чём тут C++?

Если говорить о C++, то хочу сразу сказать, что я не отношусь к тем, кто ненавидит этот язык. Если вы этим языком пользуетесь и он вам нравится — я ничего против этого не имею. Я не могу отрицать того, что C++, в сравнении с C, даёт нам два следующих преимущества. Во-первых — это улучшение структуры программ (это — поддержка пространств имён и классов; в Simula, в конце концов, есть хоть что-то хорошее). Во-вторых — это концепция RAII (если описать это в двух словах, то речь идёт о наличии конструкторов для инициализации объектов при их создании и о наличии деструкторов для очистки ресурсов после уничтожения объектов; а если глубже разработать эту идею, то можно прийти к понятию «времени жизни объекта» из Rust). Но, в то же время, у C++ есть несколько особенностей, из-за которых мне этот язык очень и очень не нравится.

Это, прежде всего — склонность языка постоянно вбирать в себя что-то новое. Если в каком-то другом языке появится какая-нибудь возможность, которая станет популярной, она окажется и в C++. В результате стандарт C++ пересматривают каждые пару лет, и при этом всякий раз в него добавляют новые возможности. Это привело к тому, что C++ представляет собой монструозный язык, которого никто не знает на 100%, язык, в котором одни возможности часто дублируют другие. И, кроме того, тут нет стандартного способа указания того, возможности из какой редакции C++ планируется использовать в коде. В Rust это поддерживается на уровне единицы компиляции. В IIRC C++ для той же цели предлагалась концепция эпох, но эта затея не удалась. И — вот одно интересное наблюдение. Время от времени мне попадаются новости о том, что кто-то в одиночку (и за приемлемое время) написал рабочий компилятор C. Но я ни разу не встречал похожих новостей о компиляторе C++.

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

И, наконец, я мог бы вообще не обращать внимания на C++, если бы этот язык не был бы связан с C и не оказывал бы на C плохое влияние. Я не говорю о ситуации, когда, говоря о C и C++, их объединяют, упоминая как «C/C++», и считая, что тот, кто знает C, знает и C++. Я имею в виду связь между языками, которая оказывает влияние и на стандарты, и на компиляторы. С одной стороны — C++ основан на C, что придало C++, так сказать, хорошее «начальное ускорение». А с другой стороны — сейчас C++, вероятно, лучше смотрелся бы без большей части своего «C-наследия». Конечно, от него пытаются избавиться, называя соответствующие конструкции устаревшими, но C-фундамент C++ никуда пока не делся. Да и будет ли популярным, скажем, некий «С++24», вышедший в виде самостоятельного языка, основанного на C++21 и лишённого большей части устаревших механизмов? Не думаю.

Воздействие компиляторов C++ на C

Вышеописанная связь C и C++ приводит к тому, что к C относятся как к C++, лишённому некоторых возможностей. Печально известным примером такого восприятия C является C-компилятор Microsoft, разработчики которого не позаботились о поддержке возможностей C99 до выхода версии компилятора 2015 года (и даже тогда разработчики придерживались стратегии «bug-for-bug compatibility», когда в новой реализации чего-либо воспроизводят старые известные ошибки; делалось это для того, чтобы пользователи компилятора не были бы шокированы, внезапно обнаружив, что вариадические макросы вдруг там заработали). Но тот же подход можно видеть и в стандартах, и в других компиляторах. Эти проблемы связаны друг с другом.

Принципиальная проблема тут заключается в том, что и стандарт C, и стандарт C++ создаются с учётом сведений, получаемых от разработчиков компиляторов, а это, в основном, C++-разработчики (и иногда возникает такое ощущение, что они ничего не знают о настоящем программировании, и полагают, что всё должно укладываться в их точку зрения, но это — тема для отдельного разговора). Я не слежу за процессом работы над стандартом, но я почти уверен, что самые неприятные аспекты C99 и более поздних версий стандарта стали результатом воздействия разработчиков компиляторов. Причём, их видение ситуации влияет не только на C++, где в этом видении есть какой-то смысл, но воздействует и на C ради упрощения компиляторов.

Я, конечно, говорю, о «неопределённом поведении», и о том, как оно рассматривается компиляторами. Эта тема стала популярным «пугалом» (код полагается на способ представления чисел с дополнением до двух; в результате в нём имеется неопределённое поведение и компилятор может выбросить оптимизировать целый блок кода!).

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

  • Поведение, определяемое архитектурой системы (то есть — то, что зависит от архитектуры процессора). Сюда, в основном, входят особенности выполнения арифметических операций. Например, если я знаю, что целевая машина использует для представления чисел дополнение до двух (нет, это не CDC 6600), то почему компилятор (который, как представляется, тоже знает об особенностях целевой архитектуры) должен считать, что система будет вести себя иначе? Ведь тогда он сможет лучше выполнять некоторые теоретически возможные оптимизации. То же применимо к операциям побитового сдвига. Если я знаю о том, что в архитектуре x86 старшие биты, выходящие за пределы числа, отбрасываются, а на ARM отрицательный сдвиг влево — это сдвиг вправо, почему я не могу воспользоваться этими знаниями, разрабатывая программу для конкретной архитектуры? В конце концов, то, что на разных платформах целые числа имеют разные размеры в байтах, считается вполне приемлемым. Компилятор, обнаружив нечто, рассчитанное на конкретную платформу, может просто выдать предупреждение о том, что код нельзя будет перенести на другую платформу, и позволить мне писать код так, как я его писал.
  • Неочевидные приёмы работы с указателями и каламбуры типизации. Такое ощущение, что плохое отношение к подобным вещам возникло лишь ради потенциальной возможности оптимизации кода компиляторами. Я согласен с тем, что использование memcpy() на перекрывающихся областях памяти может, в зависимости от реализации (в современных x86-реализациях копирование начинается с конца области) и от относительного расположения адресов, работать неправильно. Разумно будет воздержаться от подобного. А вот другие ограничения того же плана кажутся мне менее оправданными. Например — запрещение одновременной работы с одной и той же областью памяти с использованием двух указателей разных типов. Я не могу представить себе проблему, возникновение которой может предотвратить наличие подобного ограничения (это не может быть проблема, связанная с выравниванием). Возможно, сделано это для того чтобы не мешать компилятору оптимизировать код. Кульминацией всего этого является невозможность преобразования, например, целых чисел в числа с плавающей запятой с использованием объединений. Об этом уже рассуждал Линус Торвальдс, поэтому я повторяться не буду. С моей точки зрения это делается либо для улучшения возможностей компиляторов по оптимизации кода, либо из-за того, что этого требует C++ для обеспечения работы системы отслеживания типов данных (чтобы нельзя было поместить экземпляр некоего класса в объединение, а потом извлечь его как экземпляр совсем другого класса; это тоже может как-то повлиять на оптимизации).
  • Поведение кода, определяемое реализацией (то есть — поведение, которое не в точности отражает то, что предписано стандартом). Мой любимый пример подобной ситуации — это вызов функции: в зависимости от соглашения о вызове функций и от реализации компилятора аргументы функций могут вычисляться в совершенно произвольном порядке. Поэтому результат вызова foo(*ptr++, *ptr++, *ptr++) неопределён и на подобную конструкцию не стоит полагаться даже в том случае, если программисту известна целевая архитектура, на которой будет выполняться код. Если аргументы передаются в регистрах (как в архитектуре AMD64) компилятор может вычислить значение для любого регистра, который покажется ему подходящим.
  • Полностью неопределённое поведение кода. Это — тоже такой случай, когда сложно спорить со стандартом. Пожалуй, самый заметный пример такого поведения кода связан с нарушением правила, в соответствии с которым значение переменной в одном выражении можно менять лишь один раз. Вот как это выглядит в одном знаменитом примере: i++ + i++. А вот — пример, который выглядит ещё страшнее: *ptr++ = *ptr++ + *ptr++е.

C++ — это язык более высокого уровня, чем C. В то время, как в C++ имеется большинство возможностей C, использовать эти возможности не рекомендуется. Например, вместо прямого преобразования типов надо применять reinterpret_cast, а вместо указателей надо применять ссылки. От С++-программистов не ждут того, что они будут понимать низкоуровневый код так же хорошо, как C-программисты (это, конечно, лишь «средняя температура по больнице», в реальности всё зависит от конкретного программиста). И всё же, из-за того, что существует очень много C++-программистов, и из-за того, что C и C++ часто воспринимают как «C/C++», C-компиляторы часто расширяют в расчёте на поддержку ими C++ и переписывают на C++ для того чтобы упростить реализацию сложных конструкций. Это произошло с GCC, и того, кто начнёт отлаживать с помощью GDB С++-код, находящийся в .c-файлах, ждёт много интересного. Грустно то, что для того чтобы скомпилировать код C-компилятора нужен C++-компилятор, но, чему нельзя не радоваться, всё ещё существуют чистые C-компиляторы, вроде LCC, PCC и TCC.

Итоги

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

Но, по крайней мере, нельзя заменить C90 на какой-нибудь «C90 Special Edition» и сделать вид, что C90 никогда не существовало.

Оригинал данной статьи: https://habr.com/ru/company/ruvds/blog/562530/


Поделиться: 

Мы используем cookie-файлы для наилучшего представления нашего сайта. Продолжая использовать rubasic.ru, вы соглашаетесь на использование файлов cookie.
Понятно