Краткое содержание: автор статьи объясняет, почему С хорош именно на этапе обучения и прокачки мозгов будущего программиста. А через некоторое время, или даже параллельно, можно выучить более современный язык и заняться, например, Enterprise- или Web-разработкой.
Фото: Liam Briese on Unsplash
Языков программирования становится всё больше. Сейчас их около 700. Однако в основном разработчики используют 20 из них. Здесь, как и во многих других сферах, существуют рейтинги, тренды и даже мода.
Назовём навскидку несколько популярных языков. Для Enterprise-разработки активно используют Java (скоро там закрепится и Kotlin), C#, для Web-разработки — JavaScript, Go, Python и PHP, для мобильной разработки — Swift, Java/Kotlin, ну и осмелюсь назвать JavaScript (потому что может, потому что React Native). Разработчики игр часто пользуются C# и С++. Все они востребованы по нескольким причинам:
Язык С применяют при разработке программно-аппаратных решений. На С также можно частично реализовать функциональность программных продуктов, требовательных к производительности. Хотя далеко не каждый программист хочет и может работать на подобных проектах. Но вернёмся к этапу обучения.
Обычно будущие разработчики начинают программировать в школе, университете или на курсах по смене профессии. Последний вариант, к слову, сейчас сильно набрал популярность.
Рано или поздно они задаются вопросом: какой язык программирования лучше учить первым? В школе и университете на этот вопрос могут ответить за вас: чаще всего обучение там начинают с языка С/С++ (именно вот так, через «/»). Но на альтернативных обучающих площадках вряд ли вам тоже кто-то предложит просто поизучать С для расширения кругозора или прокачки мозгов. Всем хочется побыстрее, что называется, войти в ИТ. Так что, как видите, тут и там вам придётся проявить волю и самостоятельность, если решите начать изучение с языка С.
В этой статье речь всё-таки пойдёт про этап обучения и становления будущего специалиста. Поэтому, позвольте, сейчас я изложу свои аргументы, а потом вы можете изложить свои.
Более современные языки предлагают сразу несколько встроенных абстракций (или абстракций из стандартных библиотек) на все распространённые случаи жизни. Это в первую очередь относится к стандартным алгоритмическим задачам. Например, если вам нужно скопировать определённые элементы из первого массива во второй, вы можете использовать встроенный метод filter() в JavaScript. Если пишете на Java, в вашем распоряжении метод filter() из пакета java.util.stream.
JavaScript: Array.filter()
Java: stream().filter()
На языке С, особенно в учебных целях, можно предложить такую реализацию (чтобы не усложнять пример, я поменял строки на числа и изменил условие «фильтрации»):
Пытаясь реализовать такие функции руками, вы столкнётесь с фундаментальными принципами и нюансами, в которых нужно будет глубоко разобраться. В частности, самостоятельная реализация алгоритмов обработки структур данных на языке С — отличный способ научиться решать проблемы, а не искать готовые решения.
На каком бы классном и продвинутом языке вы не писали, время от времени появляются сложные задачи, которые нельзя решить с использованием стандартных библиотек и встроенных абстракций. В этих случаях такой навык просто необходим.
Кстати, разработчики, участвующие в соревновательных хакатонах, часто тренируют этот скил, решая нестандартные задачи как раз на C.
На современных высокоуровневых языках (Python, C#, Java или какой-то ещё на ваш вкус) удобно писать. Однако эти языки очень ограничивают взаимодействие с аппаратной частью. Другими словами, вы не получите полноценного опыта взаимодействия с «железом», пока не начнёте программировать на C. Современные языки программирования скрывают аппаратно-зависимые детали реализации и вместо этого эмулируют некую абстракцию. В большинстве случаев она создаётся с помощью виртуальной машины.
К сожалению, начинающие специалисты совсем не имеют представления об управлении памятью, об обработке файлов и оптимизации кода, потому что они никогда не видели даже примеров «низкоуровневого» программирования на языке C. С этой точки зрения современные языки программирования автоматизируют и скрывают слишком много. Язык С заставляет делать многое руками и писать высокооптимизированный код.
Как по мне, такое должен попробовать каждый профессиональный разработчик. Ну, как минимум, бэкендер.
Когда язык программирования предлагает набор удобных для человека абстракций, он становится менее гибким. Каждый встроенный или библиотечный метод действует как жёстко запрограммированный чёрный ящик. Другими словами, современные языки программирования скрывают подробности реализации и предлагают разработчику просто обращаться к набору интерфейсов. Ручное управление распределением динамической памяти в современных языках программирования в большинстве случаев невозможно. Между тем, C даёт вам настоящую свободу, позволяя выбирать способ реализации на более низком уровне.
Компиляторы C при должной оптимизации создают невероятно быстрый ассемблерный код. Правда, кроме того, чтобы выставлять нужные флажки оптимизации для компиляции, нужно и самому писать высокопроизводительный исходный код. В C мы должны аккуратно объявлять переменные, выделять и вовремя очищать память, обращаться к ресурсам и не забывать освобождать их. Если C был вашим первым языком, вы привыкнете рационально использовать память и ресурсы, привыкнете выбирать оптимальные структуры данных. Эта привычка сохранится, когда вы начнёте писать и на других языках.
В отличие от современных языков программирования, для реализации тех же задач на C вам придётся писать в разы больше кода. Это связано с тем, что на C многое приходится реализовывать на более низком уровне, а не использовать встроенные обёртки и абстракции из стандартных библиотек, скрывающих подробности реализации. Когда количество строк в коде увеличивается, сложность кода также растёт. Чтобы компенсировать этот эффект и поддерживать порядок в проекте, нужно стараться писать чистый и понятный код.
Написание чистого кода — это навык, который особенно востребован при работе в крупных коммерческих проектах. Если вы научитесь писать чистый код на С, то вам будет легче сделать это на другом, более простом языке.
С активным развитием C++ язык C многие перестали воспринимать как самостоятельный. Он как будто превратился в подмножество языка C++. Понятно, что фактически это не так. C++ — действительно современный язык программирования с полнофункциональным набором стандартных библиотек. На мой взгляд, C++ не должен быть первым языком, который стоит изучить. Правда, тут есть одна оговорка: если вы в дальнейшем хотите специализироваться именно на нём, то вперёд. В этом случае эти два языка можно учить параллельно, но они в какой-то момент «пересекутся» — и переход от С к С++ будет органичным и почти мгновенным.
Практически все современные языки программирования конкурируют друг с другом, вводя новый синтаксис, семантику и расширяя стандартные библиотеки и фреймворки. Как говорится, всё для людей. Это и подкупает. Но если будущие разработчики с нуля начнут изучать эти языки, они упустят ценные возможности, которые даёт C. В какой-то момент они просто не смогут сделать новый шаг в своём развитии, не зная, как работает код на более низком уровне, не зная даже, как внутри реализованы их любимые фреймворки и библиотеки.
Поэтому выберите C в качестве первого языка программирования. Его изучение займёт больше времени, но в дальнейшем поможет вам очень быстро стать экспертом в более современных языках.
Облачные серверы от Маклауд отлично подходят для разработки на С и других языках программирования.
Зарегистрируйтесь по ссылке выше или кликнув на баннер и получите 10% скидку на первый месяц аренды сервера любой конфигурации!
Фото: Liam Briese on Unsplash
Языков программирования становится всё больше. Сейчас их около 700. Однако в основном разработчики используют 20 из них. Здесь, как и во многих других сферах, существуют рейтинги, тренды и даже мода.
Назовём навскидку несколько популярных языков. Для Enterprise-разработки активно используют Java (скоро там закрепится и Kotlin), C#, для Web-разработки — JavaScript, Go, Python и PHP, для мобильной разработки — Swift, Java/Kotlin, ну и осмелюсь назвать JavaScript (потому что может, потому что React Native). Разработчики игр часто пользуются C# и С++. Все они востребованы по нескольким причинам:
- упрощённый синтаксис (в большинстве своём) и ясная семантика — на фоне языка C;
- полнофункциональный набор стандартных API;
- активная поддержка сообщества;
- растущая экосистема фреймворков и библиотек.
Язык С применяют при разработке программно-аппаратных решений. На С также можно частично реализовать функциональность программных продуктов, требовательных к производительности. Хотя далеко не каждый программист хочет и может работать на подобных проектах. Но вернёмся к этапу обучения.
Обычно будущие разработчики начинают программировать в школе, университете или на курсах по смене профессии. Последний вариант, к слову, сейчас сильно набрал популярность.
Рано или поздно они задаются вопросом: какой язык программирования лучше учить первым? В школе и университете на этот вопрос могут ответить за вас: чаще всего обучение там начинают с языка С/С++ (именно вот так, через «/»). Но на альтернативных обучающих площадках вряд ли вам тоже кто-то предложит просто поизучать С для расширения кругозора или прокачки мозгов. Всем хочется побыстрее, что называется, войти в ИТ. Так что, как видите, тут и там вам придётся проявить волю и самостоятельность, если решите начать изучение с языка С.
В этой статье речь всё-таки пойдёт про этап обучения и становления будущего специалиста. Поэтому, позвольте, сейчас я изложу свои аргументы, а потом вы можете изложить свои.
C заставляет глубоко прорабатывать решение проблемы
Более современные языки предлагают сразу несколько встроенных абстракций (или абстракций из стандартных библиотек) на все распространённые случаи жизни. Это в первую очередь относится к стандартным алгоритмическим задачам. Например, если вам нужно скопировать определённые элементы из первого массива во второй, вы можете использовать встроенный метод filter() в JavaScript. Если пишете на Java, в вашем распоряжении метод filter() из пакета java.util.stream.
JavaScript: Array.filter()
const words = ['spray', 'limit', 'elite', 'exuberant', 'destruction', 'present'];
// если длина слова больше 6, добавляем его в результирующий массив
const result = words.filter(word => word.length > 6);
console.log(result);
// получится вот такой результат: Array ["exuberant", "destruction", "present"]
Java: stream().filter()
List<String> lines = Arrays.asList("spray", "limit", "elite");
// преобразуем List в Stream
List<String> result = lines.stream()
// хотим исключить elite
.filter(line -> !"elite".equals(line))
// сформируем коллекцию и преобразуем в List
.collect(Collectors.toList());
//получится вот такой результат: spray, limit
result.forEach(System.out::println);
На языке С, особенно в учебных целях, можно предложить такую реализацию (чтобы не усложнять пример, я поменял строки на числа и изменил условие «фильтрации»):
#include <stdio.h>
#define SIZE 5
void copy_aka_filter_arr(double trg[], double src[], int n);
int main(void){
int i;
double source[SIZE] = {1.1, 2.2, 3.3, 4.4, 5.5};
double target[SIZE];
printf("Source: ");
for (i = 0; i < SIZE; i++){
printf("%5.1f ", source[i]);
}
putchar('\n');
copy_arr(target, source, SIZE);
return 0;
}
void copy_aka_filter_arr(double trg[], double src[], int n){
// копирует i-й элемент из исходного массива в новый, если он больше 3.3.
// иначе записывает в i-й элемент нового массива 0.0
int i;
for (i = 0; i < n; i++){
if (trg[i]) > 3.3){
trg[i] = src[i];
}
else{
trg[i] = 0.0;
}
}
printf("Target: ");
for (i = 0; i < SIZE; i++){
printf("%5.1f ", trg[i]);
}
putchar('\n');
}
Пытаясь реализовать такие функции руками, вы столкнётесь с фундаментальными принципами и нюансами, в которых нужно будет глубоко разобраться. В частности, самостоятельная реализация алгоритмов обработки структур данных на языке С — отличный способ научиться решать проблемы, а не искать готовые решения.
На каком бы классном и продвинутом языке вы не писали, время от времени появляются сложные задачи, которые нельзя решить с использованием стандартных библиотек и встроенных абстракций. В этих случаях такой навык просто необходим.
Кстати, разработчики, участвующие в соревновательных хакатонах, часто тренируют этот скил, решая нестандартные задачи как раз на C.
C позволяет прикоснуться к «низкоуровневому» программированию
На современных высокоуровневых языках (Python, C#, Java или какой-то ещё на ваш вкус) удобно писать. Однако эти языки очень ограничивают взаимодействие с аппаратной частью. Другими словами, вы не получите полноценного опыта взаимодействия с «железом», пока не начнёте программировать на C. Современные языки программирования скрывают аппаратно-зависимые детали реализации и вместо этого эмулируют некую абстракцию. В большинстве случаев она создаётся с помощью виртуальной машины.
К сожалению, начинающие специалисты совсем не имеют представления об управлении памятью, об обработке файлов и оптимизации кода, потому что они никогда не видели даже примеров «низкоуровневого» программирования на языке C. С этой точки зрения современные языки программирования автоматизируют и скрывают слишком много. Язык С заставляет делать многое руками и писать высокооптимизированный код.
Как по мне, такое должен попробовать каждый профессиональный разработчик. Ну, как минимум, бэкендер.
C учит свободе и ответственности
Когда язык программирования предлагает набор удобных для человека абстракций, он становится менее гибким. Каждый встроенный или библиотечный метод действует как жёстко запрограммированный чёрный ящик. Другими словами, современные языки программирования скрывают подробности реализации и предлагают разработчику просто обращаться к набору интерфейсов. Ручное управление распределением динамической памяти в современных языках программирования в большинстве случаев невозможно. Между тем, C даёт вам настоящую свободу, позволяя выбирать способ реализации на более низком уровне.
Компиляторы C при должной оптимизации создают невероятно быстрый ассемблерный код. Правда, кроме того, чтобы выставлять нужные флажки оптимизации для компиляции, нужно и самому писать высокопроизводительный исходный код. В C мы должны аккуратно объявлять переменные, выделять и вовремя очищать память, обращаться к ресурсам и не забывать освобождать их. Если C был вашим первым языком, вы привыкнете рационально использовать память и ресурсы, привыкнете выбирать оптимальные структуры данных. Эта привычка сохранится, когда вы начнёте писать и на других языках.
C мотивирует к написанию чистого кода
В отличие от современных языков программирования, для реализации тех же задач на C вам придётся писать в разы больше кода. Это связано с тем, что на C многое приходится реализовывать на более низком уровне, а не использовать встроенные обёртки и абстракции из стандартных библиотек, скрывающих подробности реализации. Когда количество строк в коде увеличивается, сложность кода также растёт. Чтобы компенсировать этот эффект и поддерживать порядок в проекте, нужно стараться писать чистый и понятный код.
Написание чистого кода — это навык, который особенно востребован при работе в крупных коммерческих проектах. Если вы научитесь писать чистый код на С, то вам будет легче сделать это на другом, более простом языке.
Пока не убедил?
С активным развитием C++ язык C многие перестали воспринимать как самостоятельный. Он как будто превратился в подмножество языка C++. Понятно, что фактически это не так. C++ — действительно современный язык программирования с полнофункциональным набором стандартных библиотек. На мой взгляд, C++ не должен быть первым языком, который стоит изучить. Правда, тут есть одна оговорка: если вы в дальнейшем хотите специализироваться именно на нём, то вперёд. В этом случае эти два языка можно учить параллельно, но они в какой-то момент «пересекутся» — и переход от С к С++ будет органичным и почти мгновенным.
Практически все современные языки программирования конкурируют друг с другом, вводя новый синтаксис, семантику и расширяя стандартные библиотеки и фреймворки. Как говорится, всё для людей. Это и подкупает. Но если будущие разработчики с нуля начнут изучать эти языки, они упустят ценные возможности, которые даёт C. В какой-то момент они просто не смогут сделать новый шаг в своём развитии, не зная, как работает код на более низком уровне, не зная даже, как внутри реализованы их любимые фреймворки и библиотеки.
Поэтому выберите C в качестве первого языка программирования. Его изучение займёт больше времени, но в дальнейшем поможет вам очень быстро стать экспертом в более современных языках.
Облачные серверы от Маклауд отлично подходят для разработки на С и других языках программирования.
Зарегистрируйтесь по ссылке выше или кликнув на баннер и получите 10% скидку на первый месяц аренды сервера любой конфигурации!
unsignedchar
На любом языке можно писать как на С. ;)
Sultansoy
Возьму за пример джаву. Там конечно есть unsafe, например, для работы с памятью, но нигде еще не встречал, чтобы про него рассказывали на курсах, редко в какой книге о нем пишут.
К тому же, не уверен, что стандартная hotspot jvm дает прям настолько полный контакт с железом, без надстроек и jni, конечно же
pin2t
На Java как раз таки пишут очень много кода "в стиле С". И дело тут не в unsafe.
Любое использование null — это код на С
Любое использование статических функций — это код на С
Любые классы с именами заканчивающимися на -er или -or — это на самом деле не классы а функции на С
И такого вот очень много в Java-мире, и пишут это все люди, которые ранее писали на С, но после перехода на Java не стали изучать как писать на Java а изучили только синтаксис.
nirom
Это что за классы такие особенные?
staticmain
Sultansoy
Не смог перейти к оригиналу, возможно глюк мобильной версии. Предоставьте, пожалуйста, ссылку.
nomn
404 и для десктопа, там лишние символы в ссылку попали, вот рабочая ссылка: betterprogramming.pub/why-every-developer-should-start-programming-with-c-39b3a87392bf
Sultansoy
Благодарю
ffriend
А в чём глубина приведённого решения на C? Больше кода вижу, отсутствие фукнций высшего порядка (которые как раз полезно изучать) вижу, решение не совсем той задачи, что на других языках, вижу. А вот глубины проработки — не вижу. Да и сама задача на особую глубину не претендует вроде как.
Оптимизировать нужно то, что рабтоает медленно. В бекенде чаще всего медленно работает база данных (при этом нужно уметь оптимизировать запросы), ввод-вывод (часто помогает асинхронщина), HTTP запросы (можно оптимизировать пулы соединений, например). Опять же, причём тут C?
Или наоборот.
nick758
Та статья как раз про тех, кто не научился писать чистый код.
ffriend
Из второго абзаца той статьи:
Понятно, что с чего бы человек не начал изучение программирования, у него есть шанс в будущем научиться делать что-то другое хорошо. Но автор этой ^ статьи достаточно категорично заявляет о необходимости изучения C, а автор статьи по ссылке наоборот предупреждает о возможной опасности низкоуровневого программирования в начале карьеры.
Вообще непонятно, на каком основании автор этой делает заявления о чистоте кода. Чистый код на C значительно отличается от чистого кода на Java, Python или JavaScript. Более того, понятие о чистоте кода сильно варьируется в зависимости от области применения — математический код будет выглядеть ужасно для веб-программиста и наоборот. Да даже в двух соседних проектах одной команды из одной области структура и стиль кода может быть совершенно разный (пример — Scala как улучшенная Java и Scala как Haskell на JVM).
Тем более непонятно заявление о глубине знаний (или, о гспд, глубине проработки проблемы). У меня есть пара знакомых без технического образования (как раз из тех, кто хочет "войти в IT"), которые сейчас изучают Java и Python. Первый недавно потратил вечер на изучение дополнительного кода для представления негативных целых чисел, другой незадолго до этого спрашивал про линии кеша процессора. Они знают про инструкции процессора, стратегии работы с памятью, относительную скорость операций и т.д. Но при этом они в жизни не видели C, потому что для достижения цели он им не нужен.
mapron
Поправьте ссылку на оригинал (у вас битая) —
betterprogramming.pub/why-every-developer-should-start-programming-with-c-39b3a87392bf
(не пишу в личку т.к. в корпортивных блогах исправления делают по 2-3 недели — если делают вообще. а читателям переходить к ориниалу нужно уже сейчас).
owlofmacloud Автор
спасибо!
я делаю исправления сразу, не стесняйтесь писать мне в личку
mapron
Я обычно так и делаю. Опечатки, и прочее. Тут особый случай был. Ну и про «сразу». Это вообще про все корп блоги, но я и вам отвечу. Вот вы ответили спустя 8 часов. За 8 часов у статьи 7 тысяч просмотров. Допустим даже 1% пользователей ходит по ссылке для перевода, это значит не меньше 70 юзеров получили битую ссылку.
У статьи недельной давности — habr.com/ru/company/macloud/blog/554650 около 6 тысяч. Не надо быть супер аналитиком чтобы понять, что большая часть просмотров и комментариев к статье в первые 4-8 часов после публикации.
Тем не менее у большинства авторов корп блогов на хабре стратегия — выложить статью и забить на фидбек на день, два, неделю или даже три. Да, некоторые отвечают на замечания в личку спустя три недели «спасибо, исправили!».
То что это мягко говоря «уже и нахрен не надо», думаю очевидно.
mapron
При этом вот код автора из его проекта:
github.com/neutralinojs/neutralinojs/blob/master/core-windows/src/server/requestparser.cpp
(т.к. neutralinojs указан им самим как его основная деятельность в личной информации, не думаю что это какой-то наколеночный проект которому он не уделял внимания)
Чет лично я не вижу никакой чистоты кода
(да, это синтаксически С++, но лично я не вижу тут именно идиоматически «плюсов», думаю вполне подходящий пример).
К сожалению проектов на C у автора не нашел :)
longclaps
Давненько я не видел goto, а тут бац — и парочка. Красота!
AnthonyMikh
Меня ещё радует наличие парочки статиков, причём с одинаковыми именами
zkutch
Мне одному кажется, что приведенный в статье пример кода копирования с фильтрацией не совсем удачно содержит выпечатку масива?
voidptr0
Чем старше становишься — тем ленивее все писать заново. С наличием языкового сахара и хороших библиотек концентрируешься уже больше на сути «написуемой» программы.
Tsimur_S
Нужно разделять обучение разработчика переходящего в 30+ лет из другой сферы, или вообще из ниоткуда («свитчера»), и разработчика получающего образование в юном возрасте(«студента»). Ключевым фактором их отличающим это наличие времени обусловленное наличием/отсутствием обязательств. В первом случае необходим быстрый результат, пусть даже ценой будущих перспектив, а во втором случае важнее планомерное, системное развитие, с охватом максимального количества дисциплин программирования, с учетом того что он возможно захочет поменять направление.
Смешивать эти две категории и советовать какие-то общие вещи — несусветная глупость.
Для «студента» не зазорно обучение начать не то что бы с С а даже с Паскаля и с ассемблера, у «свитчера» же такой роскоши нету.
alexander_lamdan
Шикарная статья.
Я вовсе начинал программировать на JavaScript, потом когда уже более менее стал сильным в веб разработке, то в сторонке стал изучать язык С, и на многие вещи я стал смотреть иначе.
gvg2000
Когда в 2018 изучал Java на онлайн-курсах, в программу обучения входил курс по алгоритмам, который читался на C, соответственно перед этим курсом надо было еще дополнительно пройти небольшой курс по основам C.
По итогу так и не понял, в чем был плюс такого варианта (предполагаю, что единственная причина — не делать отдельный курс на Java), тогда основ С из курса хватило, чтобы понять, о чем речь в курсе по алгоритмам, но в итоге и С забылся, и алгоритмы пришлось вспоминать заново, уже с решениями на Java.
Предполагаю, что опытному разработчику при необходимости изучить дополнительный язык будет значительно проще, чем новичку сначала учить С, а потом уже учить тот язык, который он хочет использовать в работе.
valeramikhaylovsky
Это не так, проект написанный на Си, код которого можно назвать чистым — очень большая редкость.
Тут скорее борьба с самим языком, чем проработка решения.
Если вы в принципе научитесь писать чистый код вне зависимости от языка, то будете это делать на любом языке.
Не многое, а всё нужно делать руками, обобщённое программирование там просто ужасно, макросы в макросах и не дай бог где-то ошибёшься, искать ошибку будешь вечность и отлаживаться не получиться. А вот высокооптимизированный код писать получится только спустя не один год практики, потому-что оптимизация начинается с архитектуры.
Emelian
А почему не с ассемблера? Хотя бы на уровне erfaren.narod.ru. Кстати, «народный» дизассемблер IdaPro, Ильфака Гильфанова, позволяет переводить ассемблерный бинарный код, типа dll и exe-файлов, в Си код.
Тем не менее, я лично предпочитаю С++, поскольку на этом языке можно проще и удобней организовать модульность. Для примера возьмем опенсорсный консольный видеопроигрыватель FFPlay.c и пробуем его внедрить в собственное оконное приложение. Я, лично, пока не перевел этот код в классы, не мог решить подобную проблему.
С другой стороны, Си-код SQLite ни в какие классы переводить не нужно. Оно и понятно, это не оконное приложение, а консольное, поэтом просто внедряем его в свой С++ проект и все прекрасно работает без «напильника».
Короче говоря, для общего развития, ассемблер и Си нужны, но не более. Для серьезной работы хорош С++. А для разовой подготовки (обработки) данных очень эффективен Питон и другие скриптовые языки. Однако краеугольным камнем программирования я считаю С++.
gshep
потому, что не стоит
cepera_ang
Нужно учить не С, а архитектуре компьютера (обычно второй или третий курс наряду с основами программирования и алгоритмами и структурами данных), особенно с учётом того, насколько абстрактная Си-машина далека от того, что реально происходит в железе. А сам С будет автоматически вытекать из рассказаного материала — это просто запись человеко-понятным языком, того что делает машина изученная только что.
А потом оказывается, что нужны и выше абстракции и это вовсе не какой-нибудь питон, а операционные системы, сети, базы данных и распределённые системы. Всё учить надо, с такой базом потом будет легко в любой области разработки разбираться.
wolfy_str
C не стоит учить… по крайней мере не олимпиадникам. Его стоило учить в начале ну максимум под конец нулевых годов. А ещё лучше в 90-е. Сейчас уже поздно. Кто знает тот знает, вундеркинды путь учат, остальные пусть мимо проходят. Я помню как изучал этот язык лет 10 назад даже больше, 12. Так вот кроме того, что это преподавалось не так что бы понятно, всё что я запомнил — это циклы, условия, какие то общие концепции не более. Вместо классов были структуры. И да намучились мы тогда, все кто учил с указателями и бинарными деревьями. Потом я узнал, что 90% ошибок в С и С++ это ошибки связанные с утечкой памяти. И забросил на долгие годы, жаль только что более современные языки, такие как Java и Python не начал учить раньше. Вообщем если хотите писать драйвера, что то низкоуровневое — велкам, но учтите, что это сделать будет не так просто сейчас.
saboteur_kiev
IMHO вообще не важно с какого языка ты начал.
Важно, чтобы ты попробовал писать на нескольких разных языках и понял их преимущества и недостатки.
inferrna
Автор путает причину и следствие: чтобы хорошо и успешно писать на C нужно быть Торвальдсом или Кармаком. Это вовсе не значит, что кем-то из них можно стать, если долго-долго
биться головой о стенупрактиковаться в C.major-general_Kusanagi
Автор желает, чтобы в IT были только Торвальдсы и Кармаки, а всех прочих желает отсечь при помощи C.
yeputons
Категорически не согласен почти со всей статьёй.
Не надо учить Си первым языком, если есть выбор! Первый императивный язык нужен для того, чтобы научиться работать с переменными, массивами, абстракциям (функции, объекты) и прочая, прочая, прочая. Чтобы было интересно этим заниматься, лучше, если проблемы будут возникать где-то в районе "как формализовать вот этот кусок предметной области?", а не "откуда взялся очередной UB?".
Как научились — можно либо лезть вниз (в том числе в Си), либо вверх (к какой-нибудь предметной области).
Нет, он заставляет детально расписать происходящее поближе к железу (а точнее — к виртуальной машине Си, привет от модели памяти), причём покороче, чтобы посвящённым меньше символов набирать. Это не то же самое, что "проработать решение проблемы".
Посмотрите на некоторые куски стандартной библиотеки: заточено под UNIX (сигналы?) и null-terminated строки в однобайтовой кодировке (причём даже с кодами 0-127, привет от знакового
char
и падающего на отрицательных числахisdigit
). Это ещё о локалях не говорим. Это активно создаёт видимость, что мы решили проблему, воспользовавшись стандартнойatof
(и огребя от локалей),strstr
(и огребя от ненормализованного юникода),tolower
(и огребя от неоднобайтовых символов).Никаких требований "подумать о проблеме" язык не выдвигает — что хочешь, то и пиши. Не угадал, что написать — получил поддых. В отличие от, например, Rust, где даже по строчке проитерироваться нельзя, не сказав явно, что именно надо — байты, code units, grapheme clusters. Вот это я бы назвал "заставляет глубоко прорабатывать".
Полагаю, что автор подразумевает всякие олимпиады по программированию. Тогда я считаю, что у меня есть некоторый опыт, чтобы ответственно заявить: фигня полная, на соревнованиях пишут на C++ и Java. Никто не пишет самостоятельно динамический массив или словарь, берут
std::vector<>
иstd::map<>
. А вот где встроенных абстракций не хватает — там пишем свои. Благо, таких задач хватает, и свой вектор там — скучнейшая часть.Автор сам пишет: "Как по мне, такое должен попробовать каждый профессиональный разработчик.". Согласен, должен попробовать. Но не первым языком, а дальше, когда уже не путаешься в отличиях цикла от условного оператора.
Придирка: если только вы не пишете интерпретатор.
Каким именно образом? Больно бьёт палкой за некоторые виды ошибок, иногда через полтора часа после запуска программы, а за некоторые не бьёт (утечки памяти)? Так себе методический приём. Нет чтобы линтеры запустить (есть для любого языка) или на этапе компиляции какие-то ошибки управления памятью ловить.
Это два принципиально разных языка с разными стилям написания кода и библиотек! Не будет никакого мгновенного перехода, будет сишный код в файле с расширением
.cpp
.unsignedchar
Если выбор между С и Pascal — лучше C :)
Во первых, С-подобный синтаксис встречается чаще чем паскале-подобный. Во вторых, научиться не стрелять в ногу с помощью С — это полезное умение.
yeputons
Если б оно ещё и стреляло стабильно… Но debug-режим, sanitizer'ы и Valgrind тут, конечно, сильно помогают.
sshikov
>Если выбор между С и Pascal — лучше C :)
А как может такое получиться, что выбор только из них? В смысле, в нормальных условиях (не будем брать условную школу, где есть проблемы с преподавателями информатики, которые сами толком ни одного языка не знают)?
AnthonyMikh
И чем именно полезно? Это же совершенно непереносимый навык.
yeputons
Умение отлаживать систему, которая умеет либо полностью работать, либо иногда необъяснимо падать с вероятность 1% в непонятном месте вполне переносимо с сишного UB на многопоточные приложения, распределённые системы и области с большими данными. Например, какие-нибудь сложные алгоритмы могут упасть после недели работы. Или если у вас десяток тысяч серверов и какая-нибудь коллизия хэшей с вероятностью 0.001% (а из-за масштабов каждый час что-нибудь да падает).
Скорее даже не умение отлаживать, а умение такое писать: чётко следовать заданной модели, не применять "очевидные рассуждения" на самом деле выходящие за рамки модели (вроде "очевидной" sequential consistency) и, когда всё-таки случилась беда, не пугаться происходящего безумия.
Antervis
AnthonyMikh
Я не про это. Я про то, что навык "не стрелять в ногу в C" не переносится на другие области и другие ЯП.
Antervis
Единственный нюанс — начинать изучать программирование с работы с памятью… скучно. Поэтому на мой взгляд идеальным вариантом будет начать курсом условного питона (базовая алгоритмика), потом продолжить си (работа с памятью, алгоритмы и структуры данных), а уже потом джава/шарп (для изучения паттернов проектирования). Жаль только на нормальную проработку такого варианта у большинства вузов нет ни часов ни квалификации преподавателей.
GarretThief
Когда-то давно я начинал учить Си и Питон примерно в одно время. И это мои эмоции от каждого из них (угадайте, где кто). Когда ты пытаешься понять, что такое функции, то тебе совершенно не до того, что звёздочка означает указатель, а тот факт, что передать двумерный массив[m][n] можно как можно как одномерный массив[m*n] (и это проще сделать, чем передавать его в двумерной виде), ломает тебе мозг и желание программировать. А замена простого
array.length
выражением типаsizeof(array_of_int) / sizeof(int)
радости этому всему не добавляет. Есть кривая обучения, и если для питона она пологая, то для Си тебе нужно одновременно изучать Си, компьютер, алгоритмы, работу с памятью, дебаг и трассировку.Несколько лет изучая питон, я понял и внутреннее устройство компьютера, и работу компиляторов/интерпретаторов, и научился гуглить проблемы и догадываться об их причинах, но когда я только начинал, то всего этого я не знал. Заставьте выйти из вима того, кто про линукс не слышал. А вот саблайм он закроет без проблем.
sshikov
Вот как так получается — большинство комментаторов считают статью в лучшем случае неверной, или категорически не согласны. А плюсы тогда откуда? Ну ведь правда же, аргументы автора оставляют желать лучшего. Нужно ли было это переводить — тоже вопрос без очевидного ответа. Есть ли среди читающих вообще хоть кто-то, кто скорее согласен с текстом? Ну или видит в нем какую-то иную пользу?
mapron
Ну не все ставят минус статье когда с ней не согласны. Тут например, перевод, для начала, я поставил плюс, т.к. хочу больше подобного контента на Хабре (спорного, провоцирующего дискуссии, но хотя бы технического)
sshikov
Ну, я не предлагаю сразу ставить минус. Я наоборот, пытаюсь выяснить, что именно в данном случае кому-то понравилось? Спорный и провоцирующий дискуссии? Да вот как-то не тянет оно на такое…
Daddy_Cool
"… и переход от С к С++ будет органичным и почти мгновенным."
Нет. Всё что можно написать на С++ можно написать на Си — он же низкоуровневый… Зачем мне классы если есть структуры? Да и без структур можно. В результате нет стимула двигаться вверх, а там много полезного/экономящего время.
alexeiz
Такое может сказать только человек, который сам на Си ничего не написал. Это по автору, кстати, видно. Куча пустых, ни на чём не основанных уверждений. Но вернёмся к чистому коду. В реальности код на Си — это хак на хаке и хаком погоняет. В Си простые вещи делать достаточно непросто. В следствие этого, рано или поздно программиста задалбывают сложности, и он начинает искать кратчайшие пути к достижению цели. Вот один пример из моей практики: я работал с человеком, который написал небольшой фреймвок для логирования событий на Си. События ассоциировались с неким контекстом, собиралась статистика, и прочее. На нормальном языке программирования, например, Питоне, вы бы сделали
with EventContext() as ctx: ...
. Но это Си. В нём подобная конструкция разворачивается в выделение памяти, явное по-элементное инициализирование структуры, указатель на которую надо где-то хранить и передовать в каждую функцию, где будет совершаться логирование, а в конце память нужно будет освободить. Как вот этот человек решил, хрен со всем этим — я сделаю контекст статической переменной! По сути, он пришёл к анти-паттерну синглтона, потому что нормальная организация работы с объектами в Си — это много кропотливой работы. И вы думаете, это единственный пример. Такого полным-полно практически в любом коде на Си.Antervis
atomic1989
Совершенно не согласен с автором. Обучать новичка сразу с сложного не получится. Новичка необходимо вводить в мир программирования с простого. По мере усвоения материала, обретения соответствующих навыков, углублять знания. На каждом этапе обучения очень важно видеть результат и важность своих знаний. Поэтому начинать путь с высокоуровневых абстракций, библиотек, фреймворков даст толчок, мотивацию к развитию с самого начала. Да и бизнесу нужны специалисты, которые дадут результат здесь и сейчас. Большинство задач решаются набором простых и готовых абстракций. Для примера: как часто приходится применять решения олимпиадных задач в бизнесе, если и часто, то какой процент разработчиков это затрагивает?
Antervis
JustDont
А если ваш стартапчик с рокстарами разорится — обидно не будет, я так понимаю? Будет очередное "мы пилили очередной мегапродукт, делающий всем хорошо, вот только несправедливый жестокий мир его подкосил"?
Antervis
во-первых, вы смешиваете в кучу «студентов-олимпиадников», «рокстаров» и специалистов с навыками низкоуровневого программирования. Во-вторых, забываете, что владение молотком не обязывает забивать им шурупы. В третьих, если «начинать путь с высокоуровневых абстракций, библиотек, фреймворков», всегда есть шанс что навыки деактуализируются веяниями моды или банальной сменой места работы. А вот база никуда не денется.
JustDont
Да нет, это вы смешиваете. У вас выше — нерешаемая "нетривиальная задачка", а тут вдруг попёрла куча других интересных людей совсем не по этой части. "Нетривиальные задачки" в бизнесе бывают нетривиальны самыми разными путями, и совсем даже не все из них решатся, если вдруг у кого-то есть "база" и он может чё-то там накодить на С. Люди, которые (обычно) успешно решают нетривиальные задачки бизнеса, связанные с кодом — это именно "звездные программисты", а не люди, у которых могучая база знаний основ С.
… и точно так же может быть почти совсем невостребованной после "банальной смены места работы". Ну впрочем можно зато проходить собеседования в конторы, которые упарываются по алгоритмам, это да.
Antervis
под «нетривиальными» я имел в виду задачи, тривиальные решения которых не проходят по требованиям, например CPU/RAM. И уже в зависимости от требований вам может понадобиться как разработчик с пониманием основ, так и рокстар. Я конечно понимаю, что в том же вебе как правило по барабану — железо ведь на стороне пользователя, но даже там поисковики снижают рейтинг тормозных сайтов, а пользователи их не уважают.
вы наверно сможете привести пример, когда при смене работы базовые знания теряют актуальность?JustDont
Ну понятненько, "если будет такая задача, которую будет сложно впихнуть в железо, то вот тут-то всё и пригодится!". Действительно, если проблема в гвоздях, а у вас чисто случайно в руках молоток — то всё складывается просто отлично. Кто бы сомневался.
Вы понимаете, в чем разница между "не востребовано" и "потеряло актуальность"?
Antervis
легко наверно пытаться обесценивать навыки, которых у вас нет...
самый простой пример — бекенд на AWS или подобных. Чем больше CPU/RAM/диска жрет ваш сервис, тем больше вы платите за это железо. Пока у вас единицы мелких контейнеров, проще закидать проблему железом. А когда сотни/тысячи, оптимизация внезапно становится чертовски выгодной. это не имеет значения если у вас нет примера.unsignedchar
Переменные, циклы, условия, да? Совсем как в С ;) На простых уровнях С очень простой язык.
Лучше бы с алгоритмов. Библиотеки с фреймворками — в одних языках одни, в других — другие, за время изучения что-то устареет, что-то выпустят новое…
yeputons
Следующий обязательный шаг и популярная абстракция — массивы и строки — уже убьёт всех начинающих программистов на Си из-за а) неопределённого поведения при выходе за границу; б) необходимости руками возиться с памятью.
major-general_Kusanagi
JustDont
Про типы данных вы случайно забыли, да? Что вы там накодите простого и интересного, не приближаясь к строкам и спискам? Числа Фибоначчи посчитаете?
unsignedchar
Всякие матрицы-шматрицы, уравнения, физика, численные методы разные, преобразования Фурье… Есть очень много задач, не требующих операций со строками.
И их тоже ;)
ЗЫ: и FizzBuzz :)
Revertis
Надо начинать изучать программирование с Бейсика! :)
А по статье — так ведь Rust все эти пункты выполняет намного лучше!