7358
Полезные материалы по всему, что может быть полезно плюсовику/сишнику. По всем вопросам @evgenycarter
Логика коэволюции компиляторов, инструментов разработки и языков программирования.
Выступление в институте iSpring 17 мая 2025 года. Огромная благодарность организаторам за приглашение и за разрешение выложить запись на моём канале.
В этой лекции мы поднимемся от самого нижнего уровня -- отдельных транзисторов до высокоуровневых языков программирования и проследим совместное развитие механизмов абстракции и инструментов разработки.
00:00 Начало: бинарные цифровые компьютеры
06:00 Мнемоническое представление и проблемы двоичного кода
14:10 Релокации и изобретение линкера
17:25 Язык ассемблера, секции и ассемблер как программа
24:30 Дизассемблер.
30:25 ABI и соглашения о вызове
35:35 Библиотеки
40:55 Проблемы ассемблера
48:10 Алгоритмические языки и компиляторы
54:45 Компилятор и его ограничения
01:03:40 Оптимизации в бэкенеде: inline и LTO
01:15:00 Гарантии по именам и механизмы абстракции
01:19:55 Завершение: абстракции не случайны
источник
📲 Мы в MAX
#cpp #programming
👉 @cpp_lib
🚀 JSON тормозит? Вы просто не умеете его готовить
Казалось бы, парсинг JSON - задача решенная. Взял библиотеку, вызвал метод, получил объект. Но что делать, когда сервис начинает задыхаться под нагрузкой, а профайлер предательски указывает на десериализацию?
Автор столкнулся именно с такой проблемой. Спойлер: просто сменой библиотеки дело не ограничилось. Пришлось погрузиться в работу с памятью и архитектурные оптимизации.
Результат впечатляет: ускорение в 4 раза по сравнению с исходным решением.
В статье подробно описан путь от «у нас проблема» до «летит как ракета». Отличный кейс по оптимизации C++ кода.
👉 Ссылка на статью: https://habr.com/ru/articles/908406/
📲 Мы в MAX
#cpp #json #optimization #highload #habr
👉 @cpp_lib
ggwave — это компактная и переносимая библиотека C/C++ для передачи и приема коротких сообщений с использованием звуковых волн.
Она позволяет устройствам обмениваться данными через звук — без необходимости в Bluetooth, Wi-Fi или других беспроводных технологиях. Это особенно полезно для коротких одноразовых взаимодействий между устройствами, которые находятся рядом друг с другом.
Поддерживает:
* Передачу текста через звук
* Возможность генерации и анализа аудиосигналов в реальном времени
* Кроссплатформенность: работает на Windows, macOS, Linux, iOS, Android и в браузере (через WebAssembly)
Примеры использования:
* Аутентификация устройств поблизости
* Обмен контактами или ссылками
* Синхронизация устройств без интернета
https://github.com/ggerganov/ggwave
📲 Мы в MAX
#cpp #programming
👉 @cpp_lib
🧑💻Пишете на Vue и давно работаете с Vue Router по привычке? Сейчас в экосистеме появляется новая опция — Kitbag Router. Лёгкий повод пересобрать подход к роутингу и обновить стек.
На открытом уроке разберём, как подключить его к проекту, настроить под свой стек и чем он принципиально отличается от Vue Router. Пошагово пройдём путь от установки до рабочих маршрутов в SPA.
Вы познакомитесь с новой библиотекой роутинга для VueJS, научитесь создавать приложения с клиентским роутингом на Kitbag Router, сравнивать его с Vue Router и осознанно выбирать инструмент под задачу.
📆Встречаемся 21 января в 20:00 МСК в преддверие старта курса «Vue.js разработчик». Регистрация открыта: https://vk.cc/cTo00r
Реклама. ООО «Отус онлайн-образование», ОГРН 1177746618576
🚀 CUTE_HEADERS - Коллекция кроссплатформенных однофайловых библиотек на C/C++ без зависимостей, в основном используемых для разработки игр.
🔹 Математика (векторы, матрицы)
🔹 Системы частиц
🔹 Аудио и таймеры
🔹 Работа с файлами
🔹 Простая физика и коллизии
🔹 Анимация и графика
🔹 И многое другое!
Все библиотеки — в одном .h файле, без зависимостей. Отлично подходят для маленьких проектов, прототипов и учебных задач.
https://github.com/RandyGaul/cute_headers
📲 Мы в MAX
#cpp #programming
👉 @cpp_lib
💻Полный перебор выглядит простым решением, пока не сталкивается с реальностью. Как только задача усложняется, перебор становится неприемлемо медленным — и именно здесь начинаются настоящие алгоритмы.
📆На открытом уроке вы напишете алгоритм Dancing Links Дональда Кнута — один из самых элегантных способов решения задач точного покрытия. Мы разберём, почему классический перебор не работает, и как четырёхсвязный список позволяет добавлять и удалять элементы практически без затрат.
Вы увидите, как несколько десятков строк кода решают задачи, которые выглядят непосильными для brute force. Реализуете алгоритм полностью, разберёте его внутреннюю механику и примените к задаче пентамино.
👉Встречаемся 12 января в 20:00 МСК в преддверие старта курса «Алгоритмы и структуры данных». Регистрация открыта: https://vk.cc/cTbGNW
Реклама. ООО «Отус онлайн-образование», ОГРН 1177746618576
Дорогие друзья, с Новым Годом!!!
Читать полностью…
📦 cpp-sort — это коллекция высокоэффективных алгоритмов сортировки, написанная на C++. Она предоставляет как классические алгоритмы (например, quicksort, mergesort), так и более современные, такие как ska_sort и spreadsort.
🔧 Основные особенности:
- Простое подключение
- Упор на производительность: множество алгоритмов оптимизированы под современные CPU
- Совместимость с std::sort и пользовательскими компараторами
- Некоторые алгоритмы устойчивы (stable), другие — нет (для повышения скорости)
- Поддержка сортировки по ключу (projection)
💡 Если ты работаешь с C++ и тебе нужна кастомная или быстрая сортировка — обязательно стоит взглянуть. Особенно если std::sort не даёт нужного эффекта.
https://github.com/Morwenn/cpp-sort
📲 Мы в MAX
#cpp #programming
👉 @cpp_lib
Сборка проектов Си и Си++: от простого к сложному. Часть I. Библиотеки
Каждый раз, в течение многих лет, собирая пилотную версию мизерного проекта или простой утилиты, мне кажется, что уж в этот раз точно обойдусь обычным скриптом для сборки, и никакие сборщики проекта мне не понадобятся. Но суровая реальность приводит меня в чувство уже в течение первых нескольких минут работы. Сначала оказывается, что до невозможности простая программка нуждается в JSON-парсере, HTTP-запросах CURL и прочих библиотеках. А по мере возбуждения хотелок эти все зависимости нарастают как снежный ком. И все мечты быстро скомпилировать страничку кода встречают на каждом шаге всё новые и новые проблемы.
Вот сегодня и расскажу о том, какие бывают способы борьбы с зависимостями и сборки проекта из множества файлов на Си++. Заодно те, кто не любят Си++, смогут порадоваться «прелестям» этого процесса. И хоть тема очень важная для программистов, но я обратил внимание, что даже многолетний опыт не гарантирует понимания этих процессов. Но сразу предупреждаю — история длинная даже с учетом всех попыток не убегать на смежные темы.
https://habr.com/ru/companies/ruvds/articles/871940/
📲 Мы в MAX
#cpp #programming
👉 @cpp_lib
🔍 Вебинар перед курсом «Программист С»: разберём устройство памяти в С до мельчайших деталей
Приглашаем на практический вебинар для тех, кто пишет код всерьёз.
Урок для embedded‑разработчиков, системные администраторов
разработчиков на C++.
На вебинаре разберём:
- как устроен процесс на уровне секций памяти;
- чем отличаются стек и куча — и где лучше размещать данные;
- как ОС выделяет память и что происходит при вызове malloc();
- что делают системные вызовы brk()/sbrk();
- как free() «узнаёт», сколько памяти высвободить.
Что вы получите:
- чёткое понимание устройства стека и кучи;
- критерии выбора: когда использовать стек, а когда — кучу;
- практические навыки работы с динамической памятью — без утечек и ошибок.
Почему это важно?
Без понимания механизмов управления памятью даже опытный разработчик может столкнуться с:
- утечками памяти;
_ segmentation fault;
- непредсказуемым поведением программы.
📅 Дата: 15.01.2026 в 20:00
👉 Регистрируйтесь сейчас: https://vk.cc/cSv0PZ
Реклама. ООО «Отус онлайн-образование», ОГРН 1177746618576
🧵 STL Renderer — это простой рендерер STL-файлов, написанный с использованием C++, OpenGL и Dear ImGui.
🔹 Функции:
- Загрузка и визуализация STL-файлов (как ASCII, так и бинарных)
- Управление камерой: вращение, масштабирование, перемещение
- Интеграция с Dear ImGui для графического интерфейса
📦 Сборка:
Проект использует CMake и требует следующих зависимостей:
- OpenGL
- GLFW
- GLAD
- Dear ImGui
🚀 Отличный старт для тех, кто хочет разобраться, как визуализировать 3D-модели в формате STL с помощью OpenGL и создать минимальный интерфейс управления сценой.
https://github.com/SynrgStudio/STL-Renderer
📲 Мы в MAX
#cpp #programming
👉 @cpp_lib
Алгоритмы на С/С++
Задача о Ханойской башне
Быстрая сортировка (quick sort)
Бинарный поиск в отсортированном массиве
Сортировка методом выбора
Сортировка методом пузырька
Минимизация просмотров в методе сортировки пузырьком
Модифицированный метод пузырька
Сортировка методом вставок
Шейкер - сортировка
источник
📲 Мы в MAX
#cpp #programming
👉 @cpp_lib
🎯 В C++ вызываемый объект — это намного больше, чем “функция”. За тридцать лет язык прошёл путь от простых указателей до мощных лямбда-выражений, которые лежат в основе современного параллелизма, асинхронности, алгоритмов и гибких архитектур.
На открытом уроке 18 декабря в 20:00 мск вы увидите эволюцию callable-подходов во всей широте: от function pointers и функторов до std::bind, std::function и современных лямбд. Разберёмся, что происходит «под капотом», как выбирать подходящий инструмент и почему именно лямбды стали стандартом промышленного C++.
Такой разбор особенно полезен тем, кто хочет писать более выразимый, модульный и безопасный код. Понимание callable-моделей даёт гибкость: проще проектировать API, реализовывать callback-механику, строить асинхронность, оптимизировать архитектуру приложения и мыслить “по-современному”.
⚡️Присоединяйтесь к открытому уроку в преддверие старта курса «C++ Developer» — получите базу, на которой строятся потоки исполнения, асинхронные модели и ключевые элементы современного C++20/23: https://vk.cc/cSn7e8
Реклама. ООО «Отус онлайн-образование», ОГРН 1177746618576
Три теоремы о сортировках
Я знаю многих программистов и руководителей в IT компаниях, которые недолюбливают математиков и в частности считают их далёкими от жизни идиотами из-за их утверждений в духе "нельзя отсортировать последовательность быстрее, чем за nlogn" -- ведь это очевидным образом неверно, есть же сортировка подсчетом и radix sort.
Нюанс в том, что описанное выше -- это распространённая некорректная трактовка одной из ключевых теорем об алгоритмах сортировок, корректное утверждение выглядит так: "не существует алгоритма, который бы гарантированно находил перестановку n элементов, приводящую к возрастающему порядку, быстрее чем за nlogn используя только операции попарного сравнения". В этом утверждении больше слов, оно более сложно в плане когнитивного восприятия, ключевой момент обозначил жирным шрифтом, чувствуете разницу?
https://habr.com/ru/hubs/cpp/articles/
📲 Мы в MAX
#cpp #programming
👉 @cpp_lib
Метапрограммирование
1. Введение в шаблоны
2. C++20: requires keyword
3. C++20: concepts
4. Operator spaceship
5. ADL и CRTP
6 (семинар). Typelist
7. Traits, Policy Based Design, Mixins
8. Полиморфизм
9 (семинар). Реализация std::function
10 (семинар). Реализация std::any без виртуальных функций
источник
📲 Мы в MAX
#cpp #programming
👉 @cpp_lib
👩💻 Паттерны проектирования на С++
Приглашаем на открытый урок.
🗓 28 января в 20:00 МСК
🆓 Бесплатно. Урок в рамках старта курса «C++ Developer. Professional».
На вебинаре сформируем чёткое понимание паттернов проектирования в C++, покажем их реальную ценность в разработке и продемонстрируем, как применять их в повседневных задачах.
Разберём несколько интересных и полезных паттернов для повседневности:
✔️ Строитель (Builder)
✔️ Адаптер (Adapter)
✔️ Легковес (Flyweight)
✔️ Команда (Command)
✔️ Мементо (Memento)
🔗 Ссылка на регистрацию: https://vk.cc/cTBlEB
Реклама. ООО «Отус онлайн-образование», ОГРН 1177746618576
Генерация лабиринтов: алгоритм Эллера
Сегодня я хотел бы рассказать о генерации идеального лабиринта — алгоритмом Эллера. Статья подойдёт всем любителям алгоритмов»
https://habr.com/ru/articles/667576/
📲 Мы в MAX
#cpp #programming
👉 @cpp_lib
Этот проект содержит исходный код игр Command & Conquer: Tiberian Dawn и Command & Conquer: Red Alert, выпущенных как часть сборника Command & Conquer Remastered Collection.
Код распространяется под лицензией GPL v3 и предоставляет возможность энтузиастам и разработчикам модифицировать, изучать и использовать движок в рамках условий лицензии. В проекте используется C++ и множество современных практик разработки, а также система сборки CMake.
Репозиторий включает:
* Исходный код движка на C++
* Документацию по сборке
* Скрипты для интеграции с игрой
* Исторический контекст разработки
Проект ориентирован на обучение, поддержку моддинга и развитие сообщества вокруг классических RTS-игр.
https://github.com/electronicarts/CnC_Remastered_Collection
📲 Мы в MAX
#cpp #programming
👉 @cpp_lib
Три теоремы о сортировках
Я знаю многих программистов и руководителей в IT компаниях, которые недолюбливают математиков и в частности считают их далёкими от жизни идиотами из-за их утверждений в духе "нельзя отсортировать последовательность быстрее, чем за nlogn" -- ведь это очевидным образом неверно, есть же сортировка подсчетом и radix sort. Нюанс в том, что описанное выше -- это распространённая некорректная трактовка одной из ключевых теорем об алгоритмах сортировок, корректное утверждение выглядит так: "не существует алгоритма, который бы гарантированно находил перестановку n элементов, приводящую к возрастающему порядку, быстрее чем за nlogn используя только операции попарного сравнения". В этом утверждении больше слов, оно более сложно в плане когнитивного восприятия, ключевой момент обозначил жирным шрифтом, чувствуете разницу?
https://habr.com/ru/articles/893452/
📲 Мы в MAX
#cpp #programming
👉 @cpp_lib
⚔️ Линус Торвальдс против C++: Почему ядро Linux остается на C?
Почему Линус Торвальдс категорически запрещает C++ в ядре Linux. Казалось бы, C++ - это "C на стероидах", но для разработки ядра эти стероиды - яд.
Разбираем основные аргументы Линуса (и почему они имеют смысл в context of kernel development).
1. Исключения (Exceptions) - зло для ядра
В C мы проверяем коды возврата. В C++ исключение может вылететь откуда угодно.
🩷Проблема: Недетерминированность. Для ядра с 30 млн строк кода это ад отладки.
🩷Риск: Если МРТ-сканер или система управления полетами "выбросит исключение" и упадет, последствия будут фатальными. Ядро требует полного контроля над потоком выполнения.
2. Скрытое управление памятью (RAII)
Линус считает, что компилятор не должен делать ничего "за спиной" программиста.
🩷Проблема: Конструкторы, деструкторы и неявные аллокации.
🩷Аргумент: В ядре управление памятью должно быть ручным и прозрачным. Зависимость от магии компилятора снижает производительность и стабильность.
3. "Жирная" объектная модель
Нужно ООП? Его можно сделать и на C. Линус утверждает, что C++ тянет за собой переусложненные иерархии и абстракции, которые потом невозможно рефакторить.
🩷Цитата: "Ограничение проекта языком C означает, что люди не смогут его испортить... идиотской чушью 'объектной модели'".
💡 Как выглядит ООП в стиле Linux (на чистом C):
Вместо классов - структуры и указатели на функции. Это дает полиморфизм без оверхеда C++.
typedef struct {
int value;
// V-table на минималках: указатель на функцию
void (*increment)(struct Person *self);
} Person;
void increment_person(Person *self) {
self->value++;
}
int main() {
Person *p = (Person*)malloc(sizeof(Person));
p->value = 5;
p->increment = increment_person; // Привязка метода
p->increment(p); // Вызов: 6
free(p);
}
Отказ от C++ - это выбор между эргономикой разработчика и стабильностью системы. Для User-space приложений C++ прекрасен. Но для ядра, от которого зависит работа миллиардов устройств (от тостеров до спутников), консерватизм C - единственно верный путь.
Практика языка C (МФТИ, 2023-2024). Допсеминар: системы сборки (make, cmake).
00:00 Зависимости и хедера
08:22 Build.sh
11:48 Makefiles и декларативная модель
19:51 Ленивые и переменные
30:52 Автоматические переменные
36:15 Первая версия makefile
41:33 Функции и wildcards
47:40 Вторая версия makefile и зависимости от хедеров
56:36 Третья итерация: почти идеальный makefile
01:06:26 Знакомство с cmake
01:19:35 Бонус. Немного больше про cmake.
01:30:40 Окончательные уроки.
источник
📲 Мы в MAX
#cpp #programming
👉 @cpp_lib
Пишем на С++ 23 под Windows 95, не вызывая подозрение у санитаров
Что, если я скажу вам, что можно писать код на свежайшем C++23 с модулями, лямбдами и constexpr, а потом запустить его на Pentium с 16 МБ ОЗУ под Windows 95? Звучит как магия или безумие, но это работает.
В этой статье я покажу, как:
Настроить компиляцию в Visual Studio 2022 под 32-битный x86 без исключений и стандартной библиотеки. Создать минимальную реализацию std::string и аллокаторов для работы на чистом WinAPI. Собрать проект линкером 1998 года и запустить его на Windows 95. Сохранить единый код для современных и ретро-систем, используя возможности C++23.
https://habr.com/ru/articles/980092/
📲 Мы в MAX
#cpp #programming
👉 @cpp_lib
Сборка проектов Си и Си++: от простого к сложному. Часть II. Сборщики
Продолжаю тему о сборке проектов на Си и Си++, первая часть которой размещена здесь.
Рецепты сборки по правилам хорошего тона должны поставляться с проектом и очень желательно, чтобы они не были привязаны к конкретной ОС или хотя бы к конкретному дистрибутиву Linux, используя специфические команды вроде apt-get, yum, emerge. Если это небольшой пет-проект выходного дня, то, конечно, в качестве рецепта сгодится и bash-скрипт. Пользователи адаптируют. Но если к проекту подключаются другие разработчики, то лучше потратить время на автоматизацию сборки, чтобы не терять его оптом в будущем. В этой части речь пойдёт об инструментах, которые используются для автоматизации процесса сборки программного обеспечения.
https://habr.com/ru/companies/ruvds/articles/875620/
📲 Мы в MAX
#cpp #programming
👉 @cpp_lib
Можно ли навсегда избавиться от утечек памяти из-за циклических ссылок?
В комментариях к статье в очередной раз услышал мнение, что поскольку невозможно в принципе гарантировать отсутствие циклических ссылок при статическом анализе кода, то в языке Rust утечки памяти из-за циклических ссылок считаются безопасными, так это не влияет на безопасное управление памятью.
При работе с памятью существует много типов ошибок, но единственные ошибки, которые до сих пор не имеют нормального способа решения, это утечки памяти из-за циклических ссылок, когда два или более объектов напрямую или косвенно ссылаются друг на друга, в результате чего доступная приложению оперативная память постепенно уменьшается, так как ее невозможно освободить автоматически.
Утечки памяти из-за циклических ссылок являются наиболее сложными для анализа. В то время как для всех остальных типов ошибок при работе с памятью уже найдены и используются различные решения, например на уровне языка программирования, с помощью сборщиков мусора, проверки заимствований или шаблонов библиотек, то проблема утечек памяти из-за циклических ссылок остается нерешенной и по сей день.
Но мне кажется, что есть очень простой способ устранить циклические ссылки в программе, который можно реализовать практически в любом типизированном языке программирования, конечно, если при этом не использовать все разрешающее ключевое слово unsafe для Rust или оператор reinterpret_cast в случае С++.
https://habr.com/ru/users/rsashka/articles/
📲 Мы в MAX
#cpp #programming
👉 @cpp_lib
📲 Мы в MAX
#cpp #programming
👉 @cpp_lib
👨💻Задачи точного покрытия — фундамент для многих алгоритмических подходов. Но пока теория лежит на полке, она мало что меняет в вашем инженерном мышлении
На открытом уроке мы разберем Dancing Links через практику: соберем пентамино на столе, представим фигуры в виде строк матрицы и разберемся, как работает поиск с возвратом. Когда алгоритм становится наглядным, вы начинаете понимать, что на самом деле происходит внутри.
Если вы хотите развивать алгоритмическое мышление, системно улучшать свои решения и уверенно чувствовать себя в задачах уровня middle+, такие разборы — обязательная часть роста.
📆 Встречаемся 22 декабря в 20:00 МСК в преддверие старта курса «Алгоритмы и структуры данных», регистрация открыта: https://vk.cc/cSslDR
Реклама. ООО «Отус онлайн-образование», ОГРН 1177746618576
Если вы хотите основательно изучить C++, ресурс LearnCpp - один из лучших бесплатных онлайн-курсов по современному C++.
Сайт охватывает:
- Основы языка (переменные, типы данных, управление потоком, функции)
- Указатели, ссылки и динамическое выделение памяти
- Работа с массивами, строками и контейнерами STL
- ООП: классы, наследование, полиморфизм, инкапсуляция
- Современные фичи C++11/14/17/20: smart pointers, lambdas, auto, ranged for, structured bindings
- Обработка исключений
- Пространства имён, шаблоны, перегрузка операторов
- Управление ресурсами (RAII)
- Работа с файлами
- Продвинутые темы: многопоточность, move-семантика, constexpr и др.
Все главы структурированы в логическом порядке, с практическими примерами, пояснениями и заданиями. Сайт постоянно обновляется, чтобы соответствовать актуальным стандартам языка.
📚 Отличный выбор для как новичков, так и опытных разработчиков, желающих освежить знания по современному C++.
https://www.learncpp.com/
📲 Мы в MAX
#cpp #programming
👉 @cpp_lib
Как написать 2D игру на C++ и чистом STL для терминала в Linux
Я PHP разработчик с опытом работы в продакшне более 8 лет. После долгого и упорного труда мне стало скучно пилить микросервисы и бэкенды в хайлоде, я решил постичь магию разработки игр. Выбрал курс по Unreal Engine 5 и C++, так как там все структурировано, понятно, и в случае необходимости есть кому задать вопрос. На первой лекции по основам С++ преподаватель сразу предложил челлендж - написать 2D игру без использования игрового движка. Идея мне понравилась и я сразу приступил к реализации.
https://habr.com/ru/post/708486/
📲 Мы в MAX
#cpp #programming
👉 @cpp_lib
Лекции С++ продвинутый поток ФПМИ 2023-24
Лекция 1. Введение в язык C++. Основные типы и операции над ними
Лекция 2. Основные команды в терминале. Компиляция программ
Лекция 3. Объявления и определения, области видимости, пространства имен
Лекция 4. Выражения и операторы. Управляющие конструкции
Лекция 5. Compile-time errors, runtime errors, undefined behavior
Лекция 6. Указатели
Лекция 7. Стековая, статическая и динамическая память
Лекция 8. Массивы, функции и указатели на функции
источник
📲 Мы в MAX
#cpp #programming
👉 @cpp_lib
🧑🏻💻Асинхронность в C++ всегда была испытанием на зрелость. Потоки, мьютексы, коллбеки — и тысячи строк кода, чтобы просто дождаться результата. Но в C++20 всё изменилось: корутины убирают боль ручного управления потоками.
На открытом уроке разберём, как работает новая модель асинхронности в C++: без громоздких конструкций и перегрузок по CPU. Вы поймёте, как устроены корутины, где их применять и почему они стали стандартом в C++20 и C++23. На практике создадим корутины-генераторы и обсудим их преимущества перед классическими потоками.
Если вы уже чувствуете, что ваш C++ проект тонет в callback hell или не масштабируется под нагрузкой — этот вебинар поможет понять, как писать современный, чистый и асинхронный код.
🔥11 декабря в 20:00 МСК. Открытый урок проходит в преддверии старта курса «C++ Developer. Professional». Присоединяйтесь и узнайте, как сделать асинхронность естественной частью вашего кода: https://vk.cc/cS9XVO
Реклама. ООО «Отус онлайн-образование», ОГРН 1177746618576