Я считаю, что C - это хороший язык для изучения принципов программирования. Что вы можете изучать на языках более низкого уровня, которые «магически» отличаются от языков высокого уровня, таких как Ruby?
Я считаю, что C - это хороший язык для изучения принципов программирования. Что вы можете изучать на языках более низкого уровня, которые «магически» отличаются от языков высокого уровня, таких как Ruby?
Ответы:
Нет никаких принципов, в общем абстрактном смысле информатики, которые присутствуют в C, которые также не присутствуют в языках более высокого уровня. Все компьютерные науки сводятся к алгоритмам, и все алгоритмы могут быть реализованы на любом языке, который полон по Тьюрингу, как Си.
Разница между C и формой языков более высокого уровня аналогична разнице, которую несет машинный код, помимо C: отношение машины к коду.
Когда вы пишете код на языках высокого уровня, вы (как правило) не заботитесь о том, как ваш код взаимодействует с машиной. Виртуальная машина, которую язык определяет для себя, скрывает многие из этих аспектов выполнения кода.
В C взаимодействие вашей программы с памятью находится на переднем крае. Это больше, чем просто необходимость управлять использованием кучи, это включает взаимодействие вашего кода со стеком и то, как простой доступ вашего кода к памяти влияет на поведение и производительность вашего кода - даже не на порядок обращений к памяти можно избежать вашего внимания, так как чтение неправильной памяти в неподходящее время может существенно снизить производительность.
В языках более высокого уровня эти вещи просто не так очевидны. Память распределяется и освобождается без вашего ведома, а иногда и без вашего ведома. Чаще всего это просто вне вашего контроля. Когда, где, как и почему большинство выделений памяти просто скрыты от вас.
Аналогично, в другом направлении, написание машинного кода или ассемблерного кода выводит на передний план еще больше деталей: почти ничего не остается вне вашей компетенции, и ваш код должен быть написан с учетом каждого распределения, каждого ресурса, каждого фрагмента данных, который проходит через регистры процессора - знания, которые настолько далеки от языков высокого уровня, что кажутся загадочными.
Я знаю, что C - хороший язык для изучения принципов программирования.
Я не согласен. В C слишком много функций, чтобы изучать принципы программирования. Возможности C для создания абстракций ужасны, и абстракция является одним из ключевых принципов программирования.
Если вы хотите узнать, как работает аппаратное обеспечение и, следовательно, испытывать некоторую механическую симпатию к машине, вам следует изучить машинный код, известный как архитектура набора команд, а также изучить структуру кэша современных процессоров. Обратите внимание, что я не рекомендую ассемблер, просто разберитесь с инструкциями по аппаратному обеспечению, чтобы вы понимали, что генерирует компилятор.
Если вы хотите изучить принципы программирования, используйте современный язык, такой как Java, C # или Swift, или один из десятков других, таких как Rust. Также изучите различные виды парадигм программирования, в том числе функциональные.
Большинство языков программирования описываются в терминах абстрактных машин. Затем они реализуются с использованием наборов инструментов, таких как компиляторы, компоновщики, ассемблеры, интерпретаторы, статические анализаторы, промежуточные языки и аппаратные средства , которые в совокупности дают результат, учитывающий, по меньшей мере, все ожидаемое поведение абстрактной машины, наблюдаемое программой. ,
C не является исключением из вышеуказанного правила. Он описывается в терминах абстрактной машины, которая не имеет представления о вашем реальном оборудовании.
Таким образом, когда люди говорят, что C учит вас, как на самом деле работает ваш компьютер, они обычно имеют в виду, что C учит вас, как работает C. Но C, будучи настолько распространенным в системном программировании, понятно, что многие люди начинают путать его с самим компьютером. И я бы лично сказал, что знание того, как работает C, часто важнее, чем знание того, как работает сам компьютер.
Но все-таки С и компьютер - это разные вещи. Фактическое аппаратное обеспечение на самом деле сложно - таким образом, что спецификация C читается как детская книга. Если вас интересует, как работает ваше оборудование, вы всегда можете найти руководство и начать писать код на ассемблере. Или вы всегда можете начать изучать цифровые схемы, чтобы самостоятельно разрабатывать оборудование. (По крайней мере, вы оцените уровень С).
Хорошо, на самом деле изучение аппаратного обеспечения включает в себя иные вещи, кроме C. Но может ли C научить программистов чему-то еще?
Я думаю, что это зависит.
Не спешите выбирать одну из этих возможностей. Я пишу код в течение многих лет, и до сих пор не знаю, какой из них является правильным, или является ли правильный ответ одним из двух, или существует ли такая вещь, как правильный ответ по этому вопросу.
Я немного склонен полагать, что вы, вероятно, в конечном итоге должны применить оба варианта, в том порядке, в котором я их описал. Но я не думаю, что это действительно технический вопрос, я думаю, что он в основном образовательный. Кажется, что каждый человек учится по-разному.
Если вы ответили на вышеупомянутый вопрос, по крайней мере, задействовав второй вариант, который я предложил, то у вас уже есть несколько ответов за плечами: все, что можно выучить на языках более высокого уровня, можно лучше выучить, заново изобрав его в C или в наименее расширен, добавив C в смесь.
Но, независимо от вашего ответа, есть несколько вещей, которые вы можете выучить почти исключительно на C (и, возможно, на нескольких других языках).
С исторически важен. Это важный этап, на который вы можете посмотреть и оценить, откуда мы пришли, и, возможно, получить немного больше информации о том, куда мы идем. Вы можете понять, почему существуют определенные ограничения, и вы можете оценить, что определенные ограничения были сняты.
С может научить вас работать в небезопасных условиях. Другими словами, это может научить вас следить за спиной, когда язык (любой язык) не может или не будет делать это для вас по любой причине. Это может сделать вас лучшим программистом даже в безопасных средах, потому что вы будете создавать меньше ошибок самостоятельно и потому что вы сможете временно отключить безопасность, чтобы выжать из своей безопасной программы некоторую дополнительную скорость (например, использование указателей) в C #), в тех случаях, когда безопасность сопровождается затратами времени выполнения.
C может научить вас тому, что у каждого объекта есть требования к памяти, расположение памяти, тот факт, что доступ к памяти можно получить через конечное адресное пространство, и так далее. Хотя другие языки не нуждаются в вашем внимании по этим вопросам, есть несколько случаев, когда приобретенная интуиция может помочь вам принимать более обоснованные решения.
C может рассказать вам о деталях связей и объектных файлов и других тонкостях через свою систему сборки. Это может дать вам полезное практическое понимание того, как нативно скомпилированная программа часто переходит от исходного кода к выполнению.
С может склонить ваш разум, чтобы мыслить по-новому через концепцию неопределенного поведения. Неопределенное поведение - одно из моих любимых понятий в разработке программного обеспечения, потому что изучение его влияния на неклассические компиляторы - это уникальное умственное упражнение, которое вы не можете получить из других языков. Тем не менее, вам придется отказаться от проб и ошибок и начать изучать язык тщательно и продуманно, прежде чем вы сможете полностью оценить этот аспект.
Но, пожалуй, самая важная реализация, которую C может дать вам, будучи небольшим языком, заключается в том, что все программирование сводится к данным и операциям . Возможно, вы захотите смотреть на вещи как на модульные классы с иерархиями и интерфейсами с виртуальной диспетчеризацией, так и на элегантные неизменяемые значения, которые обрабатываются с использованием чисто математических функций. И это все нормально - но C напомнит вам, что это всего лишь операции с данными и данными . Это полезное мышление, потому что оно позволяет вам преодолеть немало умственных барьеров.
Причина, почему С хорош для обучения, не в том, что он учит каким-либо принципам . Он учит вас, как все работает .
С можно сравнить с одним из тех старых добрых автомобилей 70-х или 80-х годов, которые были только построены для езды. Вы можете разорвать их на части, ввернуть за винтом и понять, как работает каждая деталь и как она работает вместе с другими деталями, которые вы можете взять в свои руки, чтобы посмотреть. Как только вы поймете все части, у вас будет очень четкое представление о том, как работает целое.
Современные языки больше похожи на современный автомобиль, где двигатель - это черный ящик, слишком сложный, чтобы его мог понять средний владелец автомобиля. Эти машины могут многое сделать, черт возьми, в эти дни они активно учатся водить самостоятельно. И с этой сложностью и удобством пользовательский интерфейс был значительно удален от того, что на самом деле происходит в движке.
Когда вы изучаете программирование на C, вы сталкиваетесь с множеством винтов и гаек, из которых сделан компьютер. Это позволяет развить понимание самой машины. Например, это позволяет понять, почему не стоит создавать длинную строку, подобную этой:
java.lang.String result = "";
for(int i = 0; i < components.size; i++) {
result = result + components[i];
};
(Надеюсь, это правильная Java, я давно ее не использовал ...) Из этого примера кода не очевидно, почему цикл имеет квадратичную сложность. Но это так, и именно поэтому этот код остановится, когда вам нужно объединить несколько миллионов небольших компонентов. Опытный программист на C сразу знает, где проблема, и, скорее всего, в первую очередь избежит написания такого кода.
for(int i = 0; i < strlen(s); i++)
на C, цикл также будет иметь квадратичную сложность, и он будет таким же неочевидным, как и в вашем примере с Java ;-)
Есть языки лучше, чем C, чтобы выучить «принципы программирования», особенно теоретические принципы, но C может быть полезно изучить некоторые практические, важные вещи о ремесле. Ответ от greyfade, безусловно, правильный, но ИМХО, у C вы можете многому научиться, чем самостоятельно управлять памятью. Например,
как создавать программы с полной обработкой ошибок при отсутствии исключений
как создать структуру в программе, не имея языковой поддержки для ориентации объекта
как работать с данными при отсутствии структур данных, таких как динамические списки, словари или полезная абстракция строк
как избежать распространенных ошибок, таких как переполнение массива, даже если компилятор или среда выполнения не предупреждают вас автоматически
как создавать универсальные решения без языковой поддержки шаблонов или шаблонов
и я уже говорил, что вы можете научиться управлять памятью самостоятельно, конечно? ;-)
Более того, изучая C, вы узнаете, откуда берутся синтаксические общности C ++, Java, C #, Objective C.
В 2005 году Джоэл Спольски написал рекомендацию для изучения языка C до любого другого языка более высокого уровня. Его аргументы
«Вы никогда не сможете создать эффективный код на языках более высокого уровня».
«Вы никогда не сможете работать с компиляторами и операционными системами, которые являются одними из лучших работ по программированию».
«Вам никогда не будут доверять создание архитектур для крупномасштабных проектов»
«если вы не можете объяснить, почему while(*s++ = *t++);
копирует строку, или если это не самая естественная вещь в мире для вас, ну, вы программируете на основе суеверия
Конечно, то, что он написал, безусловно, спорны, но ИМХО много его аргументы остаются в силе и сегодня.
Двумя основными абстракциями вычислений являются машины Тьюринга и лямбда-исчисление, а С - это способ экспериментировать с представлением вычислений машины Тьюринга: в основном последовательность действий низкого уровня, из которых получается желаемый результат. Но вы должны иметь в виду, что C поставляется со своей собственной моделью вычислений. Итак, изучение C научит вас низкоуровневым деталям абстрактной машины C, которая сильно отличается от реальных архитектур. Первым, чему меня учили в Си, было то, что я никогда не пытался перехитрить компилятор, применяя «умные» приемы, и, похоже, тенденция к все большей и большей оптимизации в компиляторах. Как и в других языках высокого уровня, когда вы пишете на C, компиляторы понимают, что вы ожидаете сделать на абстрактной машине C, и реализуют это на реальном оборудовании,
Итак, я имею в виду, что изучение C не обязательно даст вам хорошее представление о том, что на самом деле происходит в аппаратном обеспечении. «C близко к машине» следует понимать как «ближе, чем большинство языков более высокого уровня». Непосредственное изучение архитектуры программного обеспечения будет более полезным, если вы хотите получить более точную картину того, «как это работает».
С другой стороны, изучение C может познакомить вас с системным программированием, низкоуровневыми типами, указателями и, в частности, распределением памяти. Что касается алгоритмов обучения и структуры данных, у меня нет преимуществ изучать их на С, а не на других языках.
Это очень открытый вопрос, может не дать окончательного ответа. Вы можете выучить практически все на каждом языке, если вы понимаете внутреннюю среду языковой структуры. C заставляет вас понимать более мелкие детали, потому что он в первую очередь предназначен для написания операционной системы. Даже спустя столько лет он все еще остается одним из наиболее часто используемых языков, прежде всего благодаря встроенным системам и проектам с открытым исходным кодом. Итак, вопрос в том, что вы хотите узнать? И в каком домене?