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

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

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

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

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

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

Да что там далеко ходить, некотороые "крутые" онлайн-школы всерьез предлагают научить к 13 годам детей так, чтобы они пошли работать программистами! 🙂 Мир сходит с ума сразных концов...

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Кстати, согласно регулярно обновляющемуся индексу TIOBE (востребованность ЯП по вакансиям) в 2024 году 22% занимал Python, правда, сразу следом за ним, собирая более 40% (!!!), - шли С-подобные языки программирования: С++, Java, С, C# и JavaScript. То есть, для половины вакансий требовалось знание С-синтаксиса и логики.

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

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

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

Как выбрать язык программирования и почему ценность программиста не в выборе языка

Как выбрать первый и второй язык программирования и почему ценность программиста не в выборе языка

Привет! Меня зовут Алекс Туманов. Я руководитель направления Академии ITSTEP «Разработка программного обеспечения». За плечами 20 лет программирования на языках C, C++, C#, Java, PHP, Javascript и многих других.

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

В 90-х я писал на языке C. И это стало фундаментом карьеры в IT

Я был таким же новичком, как и все студенты Академии. Ничего не знал, но очень хотел программировать. Узнать, как устроен мир айтишников, что учат и с чем работают.

У меня была книга «Язык программирования С для чайников». Я ее очень люблю и у меня с ней только самые теплые воспоминания.

Прочитал книгу от корки до корки. Пробовал что-то делать сам, брал идеи у друзей. Они и рекомендовали учиться на языке C.

Мне понравился язык лаконичностью, красотой и строгостью. И C стал фундаментом карьеры. Как в моей истории, так и миллионов разработчиков по всему миру.

Спустя 20 лет я ни о чем не жалею. Рад тому, что начал путь именно с C. Посмотрите на тренды 2022 года. Востребованы C-подобные языки программирования: C++, C#, Java, Javascript. Недавно появился Rust. Go — тоже C-подобный язык.

Каждому, кто только начинает карьеру в IT, рекомендую обратить внимание на C — это фундаментальный язык программирования.

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

С-подобные языки формируют правильное сознание. Не просто программиста, а инженера. И да, это — разные понятия.

Программистов и инженеров отличает подход к изучению языков

Когда вы смотрите видео о программировании на Youtube или читаете блоги программистов, в голове закрадывается вопрос: «Все говорят о трендах в языках. Одни пользуются спросом. Другие умирают. Что учить?»

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

Хороший программист — всегда инженер. Он не пишет код на конкретном языке, вроде Python или Javascript. А решает задачи клиентов.

Представьте ситуацию: вы работаете над приложением для мобильного банкинга, вроде Privat24. И знаете только один язык. Вы берете этот инструмент, пишете код для приложения. С ошибками, багами — неважно. Сдаете проект, даже о них не задумываясь.

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

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

И не каждый работодатель ищет специализированного программиста. Например, Microsoft набирает в штат дженералистов — универсальных разработчиков.

То, на каком языке человек программирует — на втором месте. В Microsoft это прекрасно понимают: «Сейчас разработчик пишет на С#. Если появится проект на Java, то мы сможем передать его именно этому программисту. Он знает C#, сможет быстро выучить отличия синтаксиса языка. И приступить к работе».

Отличия синтаксиса — основа изучения второго языка

Любая профессия накладывает ограничения на мозг. Он функционирует так, чтобы помочь освоить конкретную, выбранную вами профессию. Судья знает о своей профессии в обложке канцеляризмов и сложных юридических терминов. Для нас легко сказать «человек». Но для судьи это всегда — «физическое лицо».

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

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

Язык — прикладное средство, гаечный ключ с числовой маркировкой.

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

Учить 20 языков, чтобы стать экспертом — глупо. Только от количества языков страшно: «А потяну ли я столько?» Это неправильно.

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

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

Теперь вы учите новый язык не через правила (вы их знаете), а через отличия синтаксиса. И применяете язык в необходимой для вас нише. Как в примере с мобильным приложением.

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

Например, вы занимаетесь Frontend-программированием. Если вы уже учили С, или C++, а переходите на Javascript, смотрите: «Так создаются условия в JavaScript. Так работают циклы. А вот создаются массивы – я все замечаю». И вы не тратите время на понимание того, что такое массив. Вы на C++ это выучили.

Как выбрать язык программирования, если понимания в программировании пока нет

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

Некоторым моим коллегам нравится системное программирование — разрабатывать драйвера, антивирусы, фаерволы, программные продукты для автомобильных компьютеров. И они учили С++ первым. Язык до сих пор популярен в игровой сфере.

Если вам интересно работать с веб-проектами — учите технологии Frontend (JavaScript, Html, CSS) и Backend (Java, Python, ASP.NET Core). Затем сможете выбрать одну нишу и остановиться на ней. Или стать Full-stack разработчиком и делать продукт в одиночку.

Если же не знаете, где хотите быть — возьмите язык, который всегда пользуется популярностью. Например С++. Начинайте с него. Или С#.

Я не зря рассказывал о C-подобных языках. Все, что вам потенциально нравится, связано с C — С#, Java, JavaScript.

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

Посмотрите на Youtube обзоры языков. Обратите внимание, какие задачи они решают. И приходите на специализированные мероприятия, где детально рассказывают о профессиях в IT. Послушайте презентации, задавайте вопросы. Развейте для себя все страхи и сомнения. И не акцентируйте внимание на конкретном языке — какой самый легкий, а где платят больше. 

Второй вариант — забыть о языках программирования, нише и интересах. Стать универсальным специалистом

Четко понять: чему учиться, а чему нет новичку трудно. И самостоятельно это сделать не всегда удается.

Если не хотите учиться на курсах, то попробуйте работать с ментором — опытным программистом. Он станет для вас преподавателем, поможет и расскажет, как правильно.

Проблема не только в том, чтобы найти такого программиста и мотивировать работать с вами. Есть еще несколько факторов, которые влияют на уровень и время обучения:

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

Если выбираете учебное заведение, то сразу устанавливаете цель-минимум — получить диплом и стать специалистом. А то, какой язык учить — на втором месте, или вообще пока не важно.

Если вам интересно программирование, но не знаете, чего конкретно хотите от профессии — станьте универсальным бойцом.

После обучения вы — специалист не в одной нише. Вы программист с багажом технологий. Смело выбираете сферу, где хотите быть. Осознанно и с готовой базой.

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

И не думайте сейчас, какой язык программирования учить. Если вы знаете методологию программирования, освоить предметную область второго, третьего… языков легко и интересно, как прочесть книгу или посмотреть все сезоны любимого сериала. Пробуйте!

 

Оригинал статьи

 

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

Почему я всё ещё люблю 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.
Понятно