Какие принципы выучены на C, которые нельзя выучить на языках более высокого уровня? [закрыто]

11

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

Андрей
источник
2
Вы все равно изучаете магию или ее часть. Поскольку С «ближе к металлу», вы узнаете больше о металле.
Роберт Харви
1
Я никогда полностью не понимал концепцию ссылки, пока не столкнулся с C ++.
user6245072
6
C научит вас, что такое переполнение стека. Трудный путь.
david25272
1
Я бы хотел, чтобы новые программисты начали с изучения старого доброго языка Pascal и структурированного программирования. Вы учитесь выражать себя логически и структурировано.
Бент
2
То, чему вас учат только в C и C ++, это то, что компилятор - ваш злейший враг.
CodesInChaos

Ответы:

9

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

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

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

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

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

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

greyfade
источник
6
Я никогда не понимал, почему люди всегда упоминают полноту по Тьюрингу в подобных дискуссиях. Тьюринг-полнота не имеет смысла в этом контексте; В этом отношении C ничем не отличается от других языков программирования, поэтому нечего изучать о полноте по Тьюрингу, переключаясь на C. Единственный раз, когда полнота по Тьюрингу становится актуальной, это когда обсуждается что-то, не являющееся полным по Тьюрингу, например, CSS или HTML. , Черт, если вы косоглазие достаточно трудно, даже те Тьюрингу . Более значимые вопросы сосредоточены на удобстве использования.
Роберт Харви
3
@RobertHarvey Моя точка зрения такова, что пока язык обладает разумным минимумом вычислительных возможностей, его «уровень» становится неактуальным с точки зрения алгоритмов, которые являются единственными вещами, которые имеют значение в этом контексте.
Greyfade
3
Потому что вы делаете точку зрения, которая совершенно не имеет значения для вопроса ОП. Программисты делают это постоянно; они разбрасывают фразу «полный по Тьюрингу» так, как будто она имеет некоторое практическое применение. Это не так, кроме как указать, что это не имеет значения.
Роберт Харви
2
<Ирония> Биология - это особый случай химии, который является частным случаем физики элементарных частиц. Нет ничего, что вы можете узнать из биологии, если вы знаете физику элементарных частиц. Правильно? </ Ирония>
Флориан Ф
3
Стоит отметить, что C просто требует, чтобы вы делали выделения и освобождения явными, но они по-прежнему относятся к абстрактной машине, точно так же, как в языках «более высокого уровня» - физическая (например) машина x86 по-прежнему выходит за рамки C. может создать идеально изолированную виртуальную машину, которая интерпретирует код на C, но не контролирует распределение памяти физической машины, и все же может быть на 100% соответствующей реализацией.
Теодорос Чатзигианнакис,
13

Я знаю, что C - хороший язык для изучения принципов программирования.

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

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

Если вы хотите изучить принципы программирования, используйте современный язык, такой как Java, C # или Swift, или один из десятков других, таких как Rust. Также изучите различные виды парадигм программирования, в том числе функциональные.

Эрик Эйдт
источник
12
С просто отлично подходит для создания абстракций. Вы можете писать методы на C и упаковывать данные в виде структур на C. Целые операционные системы были построены с использованием C. Что не очень хорошо в C, так это удовлетворение «современной» идеи каждого о том, как должна выглядеть объектная ориентация. лайк.
Роберт Харви
4
Не совсем. C немного выше, чем ASM. Только не ожидайте использовать классы в этом, хотя есть способы сделать это , если вы так склонны.
Роберт Харви
4
Замените «Brainfuck» на «ассемблер» в своем комментарии, и это все равно должно сохраняться. Но это не значит, что я собираюсь использовать Brainfuck в ближайшее время.
Роберт Харви
6
Ваш аргумент о возможностях C действительно имеет смысл только в том случае, если вы считаете, что классы (и сборка мусора и т. Д.) Являются необходимым элементом обучения нового программиста (чего я не делаю). Никто здесь не защищает попытки использовать классы на бесклассовом языке.
Роберт Харви
5
@ Роберт, я утверждаю, что C - это язык более низкого уровня, и как таковой он едва ли является лучшим языком для понимания принципов программирования, что мы также можем сказать о ассемблере, и то, что они являются языками более низкого уровня, не означает они как-то ближе к «истинным» принципам программирования. Вместо этого эти языки лучше понимают, как работают аппаратные средства и операционные системы, и, если это представляет интерес, я рекомендую перейти на самый низкий уровень в изучении архитектуры набора команд и машинного языка. В противном случае, есть много языков на выбор.
Эрик Эйдт
8

С и (Абстрактная) Машина

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

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

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

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

Как же вы узнали? А как ты учишься?

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

Я думаю, что это зависит.

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

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

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

Исключительно в т

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

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

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

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

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

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

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

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

Теодорос Чатзигианнакис
источник
5

Причина, почему С хорош для обучения, не в том, что он учит каким-либо принципам . Он учит вас, как все работает .

С можно сравнить с одним из тех старых добрых автомобилей 70-х или 80-х годов, которые были только построены для езды. Вы можете разорвать их на части, ввернуть за винтом и понять, как работает каждая деталь и как она работает вместе с другими деталями, которые вы можете взять в свои руки, чтобы посмотреть. Как только вы поймете все части, у вас будет очень четкое представление о том, как работает целое.

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

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

java.lang.String result = "";
for(int i = 0; i < components.size; i++) {
     result = result + components[i];
};

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

cmaster - восстановить монику
источник
Я полностью согласен. C многому научит вас о том, как все работает, что в значительной степени поможет понять: а) почему написаны языки более высокого уровня (например, что они хотели абстрагировать), и б) как работают языки более высокого уровня за кулисами, что наверняка хорошие знания, чтобы иметь. Он не будет учить принципам и может быть не таким простым, но в результате вы потеряете уважение к нему, компьютерам и более глубокому пониманию языков более высокого уровня. Также прочитайте «Назад к основному» Джоэла Спольски: joelonsoftware.com/articles/fog0000000319.html
jleach
1
Ваш ответ, конечно, в порядке, но если вы напишите for(int i = 0; i < strlen(s); i++)на C, цикл также будет иметь квадратичную сложность, и он будет таким же неочевидным, как и в вашем примере с Java ;-)
Док Браун
Не уверен, но я бы доверял компилятору Java оптимизировать это :-)
Bruno Schäpper
Опытный Java-программист также мгновенно знает, где проблема, и, скорее всего, в первую очередь избежит написания такого кода. Эта конкретная проблема обсуждается в элементарных руководствах по Java. Так что это, безусловно, не то, что можно узнать из C, но не из Java.
Питер Тейлор
@PeterTaylor Если у вас есть инструктор по Java, который знает их C, да. Но я сомневаюсь, что такого рода знания останутся, когда люди, которые знают Си, мертвы. Для программиста C это само определение C-строки, которое говорит им, что мой пример кода не может быть эффективным. Для программиста на Java это глубокие, тайные и мало используемые знания об используемых ими абстракциях, которые говорят им избегать такого рода кода. Хорошо, я немного преувеличиваю, но у вас есть идея: программист C должен знать это, программист на Java может сойти с ума, не зная этого.
cmaster - восстановить монику
2

Есть языки лучше, чем C, чтобы выучить «принципы программирования», особенно теоретические принципы, но C может быть полезно изучить некоторые практические, важные вещи о ремесле. Ответ от greyfade, безусловно, правильный, но ИМХО, у C вы можете многому научиться, чем самостоятельно управлять памятью. Например,

  • как создавать программы с полной обработкой ошибок при отсутствии исключений

  • как создать структуру в программе, не имея языковой поддержки для ориентации объекта

  • как работать с данными при отсутствии структур данных, таких как динамические списки, словари или полезная абстракция строк

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

  • как создавать универсальные решения без языковой поддержки шаблонов или шаблонов

  • и я уже говорил, что вы можете научиться управлять памятью самостоятельно, конечно? ;-)

Более того, изучая C, вы узнаете, откуда берутся синтаксические общности C ++, Java, C #, Objective C.

В 2005 году Джоэл Спольски написал рекомендацию для изучения языка C до любого другого языка более высокого уровня. Его аргументы

  • «Вы никогда не сможете создать эффективный код на языках более высокого уровня».

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

  • «Вам никогда не будут доверять создание архитектур для крупномасштабных проектов»

  • «если вы не можете объяснить, почему while(*s++ = *t++);копирует строку, или если это не самая естественная вещь в мире для вас, ну, вы программируете на основе суеверия

Конечно, то, что он написал, безусловно, спорны, но ИМХО много его аргументы остаются в силе и сегодня.

Док Браун
источник
1
C - очень хороший язык для изучения, прежде чем изучать те «вещи более высокого уровня, которые, по вашему мнению, C не поддерживает», потому что он помогает вам понять, как эти вещи действительно работают (и насколько они дороги).
Брендан
@ Брендан: Я не уверен, что цель вашего комментария заключается в том, чтобы выразить согласие, несогласие или просто знак моего ответа.
Док Браун
Программы на C, написанные профессионалами, выпускаются с переполнением буфера и серьезными сбоями. Таким образом, в то время как дисциплинированный программист может решить изучать эти вещи , язык C по своей сути не учит просто из-за обнищания. Существует множество плохих способов (и еще хуже, смешивание нескольких несовместимых способов), например, выполнять обработку ошибок без исключений и создавать структуру без объектов.
Эрик Эйдт
@ErikEidt: действительно, но особенно в экосфере C существует множество книг, учебных пособий и других материалов, которые будут посвящены этим темам. Например, «Написание твердого кода» Стива Магуайра. Конечно, если кто-то просто выберет первое издание K & R для изучения синтаксиса языка, он, вероятно, не станет лучшим программистом.
Док Браун
1

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

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

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

CoreDump
источник
1
Итак, что C может научить вас, что языки более высокого уровня не могут?
Филипп Кендалл
2
Я думаю, что неявный ответ: « Ничего , по крайней мере, не то, на что обычно претендуют сторонники». Вот так я понимаю ответ в любом случае.
Йорг Миттаг,
-3

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

Варун Мишра
источник