Які принципи вивчені на мові С, яку не можна вивчити мовами вищого рівня? [зачинено]


11

Я вважаю, що C - це гарна мова для вивчення принципів програмування. Що ви хочете вивчати мовами нижчого рівня, які "зачаровуються" далеко від тих, хто високого рівня, наприклад, Рубі?


2
Ви все-таки дізнаєтеся магію, або якусь її частину. Оскільки C "ближче до металу", ви дізнаєтесь більше про метал.
Роберт Харві

1
Я ніколи не повністю зрозумів поняття відліку, поки не зіткнувся з C ++.
user6245072

6
C навчить вас, що таке переповнення стека. Важкий шлях.
david25272

1
Я б хотів, щоб нові програмісти почали з вивчення старого хорошого Pascal та структурованого програмування. Ви вчитеся висловлювати себе логічно та структуровано.
Схилився

2
Щось, чого навчають вас лише C і C ++, це те, що компілятор - ваш найгірший ворог.
CodesInChaos

Відповіді:


9

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

Різниця в тому, що C роз'єднує форми мов вищого рівня, схожа на різницю, яку машинний код несе в порівнянні з C: Відносини машини до коду.

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

У програмі взаємодія вашої програми з пам'яттю займає чільне місце. Це більше, ніж просто те, що вам належить керувати використанням кучі, вона включає взаємодію вашого коду зі стеком, і те, як простий доступ до пам'яті коду впливає на поведінку та продуктивність вашого коду - навіть не на порядок доступу до пам'яті можна дозволити уникати вашої уваги, оскільки читання неправильної пам'яті в невідповідний час може ефективно покалічити продуктивність.

У мовах вищого рівня ці речі просто не такі очевидні. Пам'ять виділяється та розміщується без вашого відома, а іноді і без вашого спонукання. Найчастіше це просто поза вашим контролем. Коли, де, як і чому більшість виділень пам'яті просто приховані від вас.

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


6
Я ніколи не розумів, чому люди завжди згадують про Тюрінг-повноту в таких видах дискусій. Тюрінг-повнота не має сенсу в цьому контексті; У цьому плані C нічим не відрізняється від інших мов програмування, тому нічого не можна дізнатися про повноту Тьюрінга шляхом переключення на C. Єдиний час, коли повнота Тьюрінга стає актуальним, це обговорення чогось, що не є повним Тьюрінга, наприклад, CSS або HTML . Чорт, якщо ти косиш досить сильно, навіть ті, що є Тьюрінгом . Більш змістовні питання зосереджені на зручності використання.
Роберт Харві

3
@RobertHarvey Моє судження полягає в тому, що доки мова має розумний мінімум обчислювальних можливостей, її "рівень" стає неактуальним з точки зору алгоритмів, які є єдиними речами, що мають значення в цьому контексті.
greyfade

3
Тому що ви вказуєте на питання, яке абсолютно не впливає на питання ОП. Програмісти роблять це постійно; вони накидають фразу "Тюрінг-завершений", як це насправді має певне значення в практичному плані. Це не має значення, крім того, щоб зазначити, що це не має значення.
Роберт Харві

2
<іронія> Біологія - це лише особливий випадок хімії, який є особливим випадком фізики частинок. З біології нічого не можна навчитися, якщо ти знаєш фізику частинок. Так? </irony>
Флоріан F

3
Варто зазначити, що C просто вимагає від вас чітко виділити розподіли та розстановки, але вони все ще стосуються абстрактної машини, як і в мовах "вищого рівня" - фізична (наприклад) машина x86 все ще виходить за рамки C. Один може зробити ідеально VM, що інтерпретує піктограму C, але не контролює розподіл пам'яті фізичної машини, і це все ще може бути на 100% відповідне виконання.
Теодорос Чатзіґянакікіс

13

Я знаю, що C - це гарна мова, щоб вивчити принципи програмування.

Я не погоджуюсь. У C відсутня занадто багато функцій, щоб вивчити принципи програмування. Особливості C для створення абстракцій жахливі, а абстракція є одним із ключових принципів програмування.

Якщо ви хочете дізнатися, як працює апаратне забезпечення, а отже, і деяке механічне співчуття до машини, вам слід вивчити машинний код, який називається архітектурою набору інструкцій, а також вивчити структуру кешу сучасних процесорів. Зауважте, що я не рекомендую мову складання, просто зрозумійте інструкції до обладнання, щоб ви зрозуміли, що створює компілятор.

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


12
C просто чудово створює абстракції. Ви можете записати методи на C, а також можете запакувати дані як структури в C. Цілі операційні системи були побудовані за допомогою C. Що C не годиться - це задоволення "сучасної" уявлення кожного про те, як повинна виглядати орієнтація на об'єкт люблю.
Роберт Харві

4
Не зовсім. C - дещо вищий рівень, ніж ASM. Просто не сподівайтесь на використання в ньому класів, хоча є такі способи , якщо ви так схильні.
Роберт Харві

4
Замініть "Brainfuck" на "асемблер" у вашому коментарі, і це все одно має бути правдою. Але це не означає, що я скоро буду використовувати Brainfuck.
Роберт Харві

6
Ваш аргумент щодо особливостей C справді має заслугу лише в тому випадку, якщо ви вважаєте, що класи (і збирання сміття тощо) є необхідним елементом навчання нового програміста (чого я не знаю). Тут ніхто не виступає за спробу використання класів мовою без класів.
Роберт Харві

5
@Robert, мій аргумент полягає в тому, що C - це мова нижчого рівня, і як така вона навряд чи є найкращою мовою для розуміння принципів програмування, про що ми також можемо сказати про асемблері, і, оскільки вони є мовами нижчого рівня, це не означає вони якось ближче до "справжніх" принципів програмування. Ці мови краще замість того, щоб зрозуміти, як працюють апаратні та операційні системи, і якщо це цікавить, я рекомендую перейти право на найнижчий рівень, вивчаючи архітектуру набору інструкцій та мову машини. Інакше є багато мов на вибір.
Ерік Ейдт

8

C та (Анотація) машини

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

C не є винятком із наведеного правила. Він описаний у термінах абстрактної машини, яка не має уявлення про власне обладнання.

Таким чином, коли люди кажуть, що C навчає вас, як працює ваш комп'ютер, то, що вони зазвичай означають, це те, що C навчає вас, як працює C. Але C, настільки поширений у системному програмуванні, зрозуміло, що багато людей починають плутати його з самим комп'ютером. І я особисто хотів би сказати, що знати, як працює C, часто важливіше, ніж знати, як працює сам комп’ютер.

Але все-таки C і комп’ютер - це різні речі. Фактичне обладнання фактично складне - таким чином, щоб зразок C читалася як дитяча книга. Якщо вас цікавить, як працює ваше обладнання, ви завжди можете знайти посібник і почати писати код в асемблері. Або ви завжди можете почати дізнаватися про цифрові схеми, щоб ви могли самостійно спроектувати обладнання. (Принаймні, ви оціните, наскільки високий рівень C.)

Як же ви дізналися? А як ти вчишся?

Гаразд, насправді вивчення техніки вимагає речей, крім C. Але чи можна сьогодні навчати програмістів чого-небудь іншого?

Я думаю, це залежить.

  • Є такі, хто скаже, що ви можете краще засвоїти концепцію , працюючи в середовищі, яке її пропонує та заохочує, часто різними способами.
  • Є такі, хто скаже, що ви можете краще засвоїти концепцію , працюючи в середовищі, яке її не пропонує, і де вам потрібно створити її самостійно.

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

Я трохи схильний вважати, що, мабуть, ви, зрештою, повинні застосувати обидва варіанти, в порядку, про який я їх описав. Але я не думаю, що це насправді технічна справа, я думаю, що це здебільшого навчальний. Здається, кожна людина вчиться значно по-різному.

Виключно на С

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

Але, незалежно від вашої відповіді, безумовно, є кілька речей, які ви можете навчитися майже виключно з C (і, можливо, жменьки інших мов).

  • С історично важливий. Це віха, яку ви можете подивитися і оцінити, звідки ми прийшли, і, можливо, трохи зрозуміти, куди ми їдемо. Ви можете зрозуміти, чому існують певні обмеження, і ви можете зрозуміти, що певні обмеження були зняті.

  • C може навчити вас працювати в небезпечних умовах. Іншими словами, це може навчити вас спостерігати за спиною, коли мова (будь-яка мова) з будь-якої причини не може чи не зробить це для вас. Це може зробити вас кращим програмістом навіть у безпечних умовах, оскільки ви будете створювати менше помилок самостійно і тому, що зможете тимчасово вимкнути безпеку, щоб вичавити деяку додаткову швидкість із вашої інакше безпечної програми (наприклад, використання покажчиків в C #), у тих випадках, коли безпека пов'язана з витратами на виконання.

  • C може навчити вас, що кожен об’єкт має вимоги до пам’яті, компонування пам’яті, того, що до пам’яті можна отримати доступ через обмежений адресний простір тощо. Хоча інші мови не потребують вашої уваги з цих питань, є кілька випадків, коли певна набута інтуїція може допомогти вам прийняти більш обґрунтовані рішення.

  • C може навчити вас про деталі файлів зв’язків та об'єктів та інші тонкощі через систему складання. Це може дати вам корисне практичне розуміння того, як на самому складена програма часто переходить від вихідного коду до виконання.

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

  • Але, мабуть, найважливіше усвідомлення, яке може надати C, будучи малою мовою, - це ідея, що все програмування зводиться до даних та операцій . Ви можете подивитися на речі як на модульні класи з ієрархіями та інтерфейси з віртуальною розсилкою, або на елегантні незмінні значення, якими керують за допомогою чисто математичних функцій. І це все добре - але C нагадає вам, що це все лише дані + операції . Це корисне мислення, оскільки дозволяє знищити досить багато психічних бар'єрів.


5

Причина, чому C хороша для навчання, полягає не в тому, що вона викладає будь-які принципи . Це вчить вас, як все працює .

C можна порівняти з одним із тих гарних старих автомобілів 70-х чи 80-х, які тільки побудували для заїзду. Ви можете розірвати їх, закрутити гвинтом і зрозуміти, як працює кожна деталь, і як вона працює разом з іншими частинами, які ви можете взяти в руки, щоб подивитися. Після того, як ви зрозумієте всі частини, ви маєте дуже чітку картину, як функціонує ціле.

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

Коли ви вивчаєте програмування на C, ви стикаєтесь з великою кількістю гвинтів і гайок, з яких виготовлений комп'ютер. Це дозволяє розвинути розуміння самої машини. Наприклад, це дозволяє зрозуміти, чому не годиться будувати довгий рядок, як це:

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

(Я сподіваюся, що це правильна Java, я її не використовував давно ...) З цього прикладу коду не очевидно, чому цикл має квадратичну складність. Але це так, і це причина, що цей код прийде до шліфування, коли у вас є кілька мільйонів дрібних компонентів для об'єднання. Досвідчений програміст на C одразу знає, де проблема, і, швидше за все, уникне написання такого коду.


Я згоден повністю. C навчить вас багато чому про те, як все працює, що йде довгим шляхом до розуміння а) чому були написані мови вищого рівня (наприклад, що вони мали на меті абстрагуватися), і б) як ці мови вищого рівня працюють за лаштунками, які напевно хороші знання мати. Це не навчить принципам і може бути не таким простим, але ви відійдете з повагою до нього, комп'ютерів та більш глибокого розуміння мов вищого рівня. Читайте також Повернутися до Основного Джоела Спольського: joelonsoftware.com/articles/fog0000000319.html
jleach

1
Ваша відповідь, безумовно, прекрасна, але якщо ви пишете for(int i = 0; i < strlen(s); i++)на C, цикл також матиме квадратичну складність, і це так само непомітно, як у вашому прикладі Java ;-)
Doc Brown

Не впевнений, але я б довірив компілятору Java оптимізувати це :-)
Бруно Шеппер

Досвідчений програміст Java також моментально знає, де проблема, і, швидше за все, уникне написання такого коду. Цей конкретний питання обговорюється в елементарних навчальних програмах Java. Тож це, звичайно, не те, що можна вивчити на C, але не на Java.
Пітер Тейлор

@PeterTaylor Якщо у вас є інструктор з Java, який знає їх C, так. Але я сумніваюся, що подібне знання залишиться навколо, коли люди, які знають С, померли. Для програміста C це саме визначення того, що таке C-рядок, що говорить їм, що мій приклад коду не може бути ефективним. Для Java-програміста це глибоке, затаємничене і мало використовуване знання про те, які вони використовуються, що дозволяє їм уникати подібного коду. Гаразд, тут я трохи перебільшую, але ви отримуєте думку: Програміст C повинен це знати, Java-програміст може піти, не знаючи цього.
cmaster - відновити моніку

2

Є кращі мови, ніж C, щоб вивчити "принципи програмування", особливо теоретичні принципи, але C може бути корисним, щоб дізнатися деякі практичні, важливі речі про ремесло. Відповідь greyfade точно вірна, але IMHO ви можете дізнатися більше від C, ніж як самостійно керувати пам'яттю. Наприклад,

  • як створити програми з повним поводженням з помилками за відсутності винятків

  • як створити структуру в програмі, не маючи жодної мовної підтримки для орієнтації на об'єкт

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

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

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

  • і я згадав, ви, звичайно, можете навчитися самостійно керувати пам’яттю? ;-)

Більше того, вивчаючи C, ви дізнаєтесь, звідки беруться синтаксичні спільності C ++, Java, C #, Цілі C.

У 2005 році Джоел Спольський написав рекомендацію щодо вивчення мови С будь-якої іншої мови вищого рівня. Його аргументи є

  • "ви ніколи не зможете створити ефективний код на мовах вищого рівня."

  • "Ви ніколи не зможете працювати над компіляторами та операційними системами, які є одними з найкращих завдань програмування навколо."

  • "Вам ніколи не будуть довіряти створювати архітектури для масштабних проектів"

  • "якщо ви не можете пояснити, чому while(*s++ = *t++);копіює рядок, або якщо це для вас не найприродніше у світі, ви програмуєте на основі забобонів

Звичайно, те, що він написав, безумовно, є дискусійним, але багато його аргументів ІМХО є чинними і сьогодні.


1
C - це дуже гарна мова, яку слід вивчити, перш ніж вивчити ті "речі вищого рівня, які, на вашу думку, не підтримує", тому що вони допомагають зрозуміти, як ці речі насправді працюють (і наскільки вони дорогі).
Брендан

@Brendan: Я не впевнений, чи має намір ваш коментар висловити згоду, незгоду чи просто сторону моєї відповіді.
Док Браун

Програми на C, написані професіоналами, випускаються із перевиконанням буфера та жорсткими збоями. Отже, хоча дисциплінований програміст може вирішити вчитися цим речам , мова С по суті не викладає просто збіднення. Існує маса поганих способів (і ще гірше, змішування декількох непослідовних способів), щоб зробити обробку помилок без винятків і створити структуру, наприклад, без об'єктів.
Ерік Ейдт

@ErikEidt: дійсно, але особливо в екосфері С існує багато книг, навчальних посібників та інших матеріалів, які стосуватимуться цих тем. Наприклад, "Написання твердого коду" Стіва Магуайра. Звичайно, якщо хтось просто вибирає перше видання K&R для вивчення синтаксису мови, він, ймовірно, не стане кращим програмістом.
Doc Brown

1

Дві основні абстракції обчислень - це машини Тьюрінга та обчислення Ламбди, а C - це спосіб експериментувати з обчисленням машини Тьюрінга: переважно послідовність дій низького рівня, з яких виходить бажаний результат. Але ви повинні мати на увазі, що C поставляється з власною моделлю обчислення. Таким чином, вивчення C навчить вас деталі низького рівня абстрактної машини C, яка сильно відрізняється від фактичної архітектури. Одне з перших, що мене навчили в C, - це ніколи не намагатися перехитрити компілятора, застосовуючи «розумні» трюки, і, здається, тенденція до все більшої оптимізації в компіляторах. Як і в інших мовах високого рівня, коли ви пишете на C, компілятори начебто розуміють, що ви очікуєте зробити на абстрактній машині С і зробити це на фактичному обладнання,

Отже, я маю на увазі те, що вивчення C не обов'язково дасть тобі хорошу картину того, що насправді відбувається в апараті. "C близький до машини" слід розуміти як "ближче, ніж більшість мов вищого рівня". Навчання архітектурі програмного забезпечення буде більш корисним, якщо ви хочете більш точну картину "як це працює".

З іншого боку, навчання C може ознайомити вас із системним програмуванням, типами низького рівня, покажчиками та зокрема розподілом пам'яті. Що стосується алгоритмів навчання та структури даних, то я не маю переваги вивчати їх на C, а не на інших мовах.


1
Отже, що може навчати вас, що мови вищого рівня не можуть?
Філіп Кендалл

2
Я думаю, що неявна відповідь: " Нічого , принаймні, не те, на що зазвичай заявляють прихильники". Ось як я розумію відповідь все одно.
Йорг W Міттаг

-3

Це дуже відкрите запитання, яке не може не дати остаточної відповіді. Ви можете навчитися майже всім з кожної мови за умови розуміння внутрішніх мовних рамок. C змушує вас зрозуміти більш низькі деталі, оскільки він був розроблений в основному для написання операційної системи. Навіть через стільки років це все ще одна з найбільш використовуваних мов насамперед завдяки вбудованим системам та проектам з відкритим кодом. Отже, питання - що ви хочете навчитися? І в якому домені?

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.