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


Фото: 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% скидку на первый месяц аренды сервера любой конфигурации!