Я вважаю, що C - це гарна мова для вивчення принципів програмування. Що ви хочете вивчати мовами нижчого рівня, які "зачаровуються" далеко від тих, хто високого рівня, наприклад, Рубі?
Я вважаю, що 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, будучи малою мовою, - це ідея, що все програмування зводиться до даних та операцій . Ви можете подивитися на речі як на модульні класи з ієрархіями та інтерфейси з віртуальною розсилкою, або на елегантні незмінні значення, якими керують за допомогою чисто математичних функцій. І це все добре - але 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 точно вірна, але IMHO ви можете дізнатися більше від C, ніж як самостійно керувати пам'яттю. Наприклад,
як створити програми з повним поводженням з помилками за відсутності винятків
як створити структуру в програмі, не маючи жодної мовної підтримки для орієнтації на об'єкт
як поводитися з даними за відсутності таких структур даних, як динамічні значні списки, словники чи корисна абстракція рядків
як уникнути поширених помилок, таких як переповнення масиву, навіть коли компілятор або часове середовище не попереджають вас автоматично
як створити загальні рішення, не маючи мовної підтримки шаблонів чи дженериків
і я згадав, ви, звичайно, можете навчитися самостійно керувати пам’яттю? ;-)
Більше того, вивчаючи C, ви дізнаєтесь, звідки беруться синтаксичні спільності C ++, Java, C #, Цілі C.
У 2005 році Джоел Спольський написав рекомендацію щодо вивчення мови С будь-якої іншої мови вищого рівня. Його аргументи є
"ви ніколи не зможете створити ефективний код на мовах вищого рівня."
"Ви ніколи не зможете працювати над компіляторами та операційними системами, які є одними з найкращих завдань програмування навколо."
"Вам ніколи не будуть довіряти створювати архітектури для масштабних проектів"
"якщо ви не можете пояснити, чому while(*s++ = *t++);
копіює рядок, або якщо це для вас не найприродніше у світі, ви програмуєте на основі забобонів
Звичайно, те, що він написав, безумовно, є дискусійним, але багато його аргументів ІМХО є чинними і сьогодні.
Дві основні абстракції обчислень - це машини Тьюрінга та обчислення Ламбди, а C - це спосіб експериментувати з обчисленням машини Тьюрінга: переважно послідовність дій низького рівня, з яких виходить бажаний результат. Але ви повинні мати на увазі, що C поставляється з власною моделлю обчислення. Таким чином, вивчення C навчить вас деталі низького рівня абстрактної машини C, яка сильно відрізняється від фактичної архітектури. Одне з перших, що мене навчили в C, - це ніколи не намагатися перехитрити компілятора, застосовуючи «розумні» трюки, і, здається, тенденція до все більшої оптимізації в компіляторах. Як і в інших мовах високого рівня, коли ви пишете на C, компілятори начебто розуміють, що ви очікуєте зробити на абстрактній машині С і зробити це на фактичному обладнання,
Отже, я маю на увазі те, що вивчення C не обов'язково дасть тобі хорошу картину того, що насправді відбувається в апараті. "C близький до машини" слід розуміти як "ближче, ніж більшість мов вищого рівня". Навчання архітектурі програмного забезпечення буде більш корисним, якщо ви хочете більш точну картину "як це працює".
З іншого боку, навчання C може ознайомити вас із системним програмуванням, типами низького рівня, покажчиками та зокрема розподілом пам'яті. Що стосується алгоритмів навчання та структури даних, то я не маю переваги вивчати їх на C, а не на інших мовах.
Це дуже відкрите запитання, яке не може не дати остаточної відповіді. Ви можете навчитися майже всім з кожної мови за умови розуміння внутрішніх мовних рамок. C змушує вас зрозуміти більш низькі деталі, оскільки він був розроблений в основному для написання операційної системи. Навіть через стільки років це все ще одна з найбільш використовуваних мов насамперед завдяки вбудованим системам та проектам з відкритим кодом. Отже, питання - що ви хочете навчитися? І в якому домені?