C++ Academy
15.5K subscribers
845 photos
143 videos
1 file
760 links
По всем вопросам- @workakkk

РКН: clck.ru/3FmxJF

#VRHSZ
Download Telegram
C++23 добавил `std::expected`, и это одна из самых практичных вещей в языке за последние годы.

Идея простая: функция возвращает либо нормальный результат, либо ошибку. Без исключений, без output-параметров и без неявного control flow, который потом сложно отследить.

Например, парсер заголовка может вернуть uint32_t, если всё хорошо, или std::error_code, если буфер слишком короткий. Вызывающая сторона сразу видит: здесь результат может быть ошибкой, её нельзя «случайно забыть» так же легко, как при старом стиле с кодами возврата.

Это особенно удобно для системного кода, сетевых протоколов, парсеров, embedded и всего, где исключения либо запрещены, либо нежелательны.

std::expected не делает обработку ошибок магической. Он просто заставляет контракт функции быть честным: успешный результат и возможная ошибка описаны прямо в типе.
👍184
Cuckoo hashing даёт O(1) lookup в худшем случае

Не амортизированно.

Не «в среднем».

А именно worst case.

Идея красивая: у каждого ключа есть ровно две возможные позиции в таблице.

Поэтому поиск тупо проверяет оба места и заканчивается.


return table1[h1(key)] == key
|| table2[h2(key)] == key;


Вставка работает интереснее: если место занято, новый ключ «выталкивает» старый в его альтернативную позицию.

Отсюда и название: как кукушка, которая выкидывает чужие яйца из гнезда.

Если начинается цикл, таблицу перестраивают с новыми хеш-функциями.

Алгоритм предложили Rasmus Pagh и Flemming Rodler в 2001 году.

И это не просто академическая штука: Linux kernel использует cuckoo hashing в connection tracking table.

Один из тех случаев, когда простая идея даёт очень сильную гарантию по lookup.
🔥114👍1🥰1
🔥 Хочешь быстрее расти в IT? Хватит учиться в одиночку

В IT прокачивается тот, кто каждый день видит сильные идеи, новые инструменты, реальные задачи, вакансии и разборы.

Окружение решает больше, чем кажется.

Собрал папки и каналы, где можно быстрее влиться в нужное направление, следить за трендами и не вариться в своём пузыре.

AI: t.iss.one/ai_machinelearning_big_data
Python: t.iss.one/pythonl
Linux: t.iss.one/linuxacademiya
Хакинг: t.iss.one/linuxkalii
DevOps: t.iss.one/DevOPSitsec
Docker: t.iss.one/DevopsDocker
Golang: t.iss.one/Golang_google
Rust: t.iss.one/rust_code
C++: t.iss.one/cpluspluc
C#: t.iss.one/csharp_1001_notes
Java: t.iss.one/java_library
JavaScript: t.iss.one/javascriptv
React: t.iss.one/react_tg
Frontend: t.iss.one/front
PHP: t.iss.one/phpshka
Android: t.iss.one/android_its
Мобильная разработка: t.iss.one/mobdevelop
Базы данных: t.iss.one/sqlhub
Data Science: t.iss.one/data_analysis_ml
Big Data: t.iss.one/bigdatai
Математика: t.iss.one/data_math
Физика: t.iss.one/fizmat
Kubernetes: t.iss.one/kubernetc
GameDev: https://t.iss.one/gamedev
Haskell: t.iss.one/haskell_tg

Собеседования и карьера:

DS собеседования: t.iss.one/machinelearning_interview
Python собеседования: t.iss.one/python_job_interview

Папка с вакансиями: t.iss.one/addlist/_zyy_jQ_QUsyM2Vi
Папка Go разработчика: t.iss.one/addlist/MUtJEeJSxeY2YTFi
Папка Python разработчика: t.iss.one/addlist/eEPya-HF6mkxMGIy
Папка ML: https://t.iss.one/addlist/2Ls-snqEeytkMDgy
Папка Frontend: https://t.iss.one/addlist/mzMMG3RPZhY2M2Iy

Полезное сверху:

ИТ-мемы: t.iss.one/memes_prog
Английский для программистов: t.iss.one/english_forprogrammers
ИИ и технологии: t.iss.one/vistehno
954 ГБ open-source курсов: @courses
ИТ-книги бесплатно: https://t.iss.one/addlist/BkskQciUW_FhNjEy

Max Ai: https://max.ru/ai_machinelearning_big_data
Max python: https://max.ru/pythonl
ТЕХНО: https://max.ru/vistehno
Max Go: https://max.ru/Golang_google
Max Linux: https://max.ru/linuxkalii
Devops: https://max.ru/DevOPSitsec
C#: https://max.ru/csharp_ci
C++: https://max.ru/cpluspluc
SQL: https://max.ru/sqlhub
Java: https://max.ru/javatg

Подписывайся на нужные направления и собирай себе ленту, которая реально двигает вперёд.

Пока кто-то листает шум, ты будешь видеть инструменты, задачи и идеи, которые помогают расти в профессии.
💔41👍1🔥1
🤖 RSA почти никогда не делит числа по модулю напрямую

Операции с огромными числами слишком дорогие, поэтому реализации RSA используют редукцию Монтгомери.

Идея Питера Монтгомери из 1985 года:

выбирается R = 2^k
деление на R заменяется битовым сдвигом
модульные вычисления выполняются через умножения, сложения и сдвиги

За счёт этого быстрее считается:

a^e mod N

Это критично для:

шифрования и расшифровки
цифровых подписей
TLS-соединений
банковских операций

Редукция Монтгомери десятилетиями работает внутри криптографических библиотек, хотя большинство пользователей даже не знает о её существовании.
Please open Telegram to view this post
VIEW IN TELEGRAM
5👍3🔥3🤔2
✔️ Furtex: исследовательский набор для Linux post-exploitation и обхода EDR

В open source вышел Furtex - низкоуровневый toolkit для изучения техник post-exploitation и evasion в Linux.

Проект построен вокруг io_uring, BPF и eBPF. Автор намеренно отказался от liburing и готовых фреймворков: взаимодействие с ядром реализовано через raw syscalls.

В репозитории собраны эксперименты для:

- анализа возможностей io_uring
- исследования BPF-карт и программ
- тестирования Linux EDR
- изучения видимости событий для средств мониторинга
- проверки защитных правил Falco
- исследования сетевых и процессных механизмов ядра

Furtex интересен специалистам по Linux security, разработчикам EDR и red team-инженерам, которым важно понимать, какие действия могут проходить мимо привычных точек наблюдения.

Автор отдельно подчёркивает: проект предназначен только для разрешённых исследований и тестирования собственной инфраструктуры.

https://github.com/MatheuZSecurity/Furtex

#linux #cybersecurity #ebpf #io_uring #research
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥5👍31
⚡️ C++26: прямой доступ к типу внутри parameter pack

В C++26 появился pack indexing. Теперь тип по индексу можно получить напрямую из набора параметров:


template<std::size_t I, typename... Ts>
using nth_t = Ts...[I];

using Second = nth_t<1, int, double, std::string>;
// Second = double


Индексация начинается с нуля.

Раньше для этого использовали std::tuple_element_t, вспомогательные шаблоны или рекурсию:


template<std::size_t I, typename... Ts>
using old_nth_t = std::tuple_element_t<I, std::tuple<Ts...>>;


Новый синтаксис короче и понятнее:


Ts...[I]


Пригодится в шаблонных библиотеках, метапрограммировании, traits и compile-time API.
👍157🔥3
Даже формально верифицированный компилятор может ошибаться

В 2011 году исследователи тестировали CompCert случайно сгенерированными C-программами и нашли wrong-code баг в таком выражении:

return -1 <= (1 && x);

Правильный результат — 1, но CompCert 1.6 для PowerPC возвращал 0.

Ошибка оказалась не в доказанно корректном оптимизаторе, а в неверифицированном фронтенде.

Формальная верификация защищает только те части системы, для которых действительно построено доказательство.
🤔13👍21🔥1🥰1
✔️ std::exchange: правильный move-конструктор без double free

Move-конструктор через ручное копирование полей это ловушка. Скопировал указатель, забыл занулить источник, и оба объекта в деструкторе зовут delete по одному адресу. Double free: иногда падает сразу, иногда через неделю в проде.

std::exchange закрывает вопрос одним вызовом. Он забирает ресурс и кладёт в источник безопасное значение:


Handle(Handle&& other)
: ptr(std::exchange(other.ptr, nullptr)) {}


Новый объект получает старый указатель, а в other.ptr уезжает nullptr. delete по nullptr это no-op, поэтому перемещённый объект уничтожается безопасно, и владелец у ресурса ровно один.

Именно так пишет стандартная библиотека внутри. Коротко, exception-safe, без шанса забыть про зануление. Одна функция против двух строк, на которых легко ошибиться.

Правило короткое: перемещаешь владеющий указатель, бери std::exchange.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍146🔥3
🌍🚀 Pointerverse: Версионный контроль для ветвящихся миров

Pointerverse — это детерминированный движок для создания проверяемых миров. Вы описываете мир как программу, создаете контент-адресованные коммиты и проверяете каждое изменение по заданным законам. Это позволяет воспроизводить историю и анализировать последствия изменений.

🚀Основные моменты:
- Детерминированное управление историей с проверкой на соответствие законам.
- Возможность ветвления и сравнения различных сценариев.
- Полная воспроизводимость и защита от подделок с помощью Merkle DAG.
- Поддержка написания собственных миров с использованием языка .pv.

📌 GitHub: https://github.com/farukalpay/Pointerverse
🤣2
🛠️ Cup: C-Based Build System

Cup — это система сборки, написанная на C, позволяющая использовать C в качестве языка сценариев. Она поддерживает сложную логику сборки и интеграцию с инструментами разработки, такими как LSP и отладчики.

🚀Основные моменты:
- Полная поддержка C без использования DSL.
- Автоматическое обновление и кэширование сборок.
- Поддержка Windows, Linux и macOS.
- Генерация файлов конфигурации для популярных IDE.
- Легковесные сборки и параллельные команды.

📌 GitHub: https://github.com/howaajin/cup

#c
👍3🔥2
🔥 Как найти младший установленный бит без цикла

Этот трюк возвращает позицию самого правого бита 1 в 32-битном числе:


static const int table[32] = {
0, 1, 28, 2, 29, 14, 24, 3,
30, 22, 20, 15, 25, 17, 4, 8,
31, 27, 13, 23, 21, 19, 16, 7,
26, 12, 18, 6, 11, 5, 10, 9
};

int lowest_set_bit(uint32_t v)
{
return table[((v & -v) * 0x077CB531U) >> 27];
}


Выражение v & -v изолирует младший установленный бит.

Затем результат умножается на константу 0x077CB531 из последовательности де Брёйна. Для каждой из 32 возможных позиций старшие 5 бит произведения образуют уникальный индекс.

Остаётся одно обращение к таблице - и позиция найдена без перебора всех битов.

Важно: функция рассчитана на v != 0.

В современном коде также стоит проверить std::countr_zero() или __builtin_ctz() - компилятор часто превращает их в одну инструкцию процессора.
👍10🔥7❤‍🔥21
Doom в 1993 работал на 486 и 4 МБ RAM. А современные игры почему едят 16 ГБ?

Секрет был в BSP-дереве: уровень заранее делился на области, а движок во время рендера просто обходил дерево в нужном порядке. Без z-buffer, без лишней магии, без пересчёта видимости с нуля каждый кадр.

Кармак буквально заставил геометрию работать вместо железа.

Подписывайся, тут ещё много таких историй про код, который унижает современные «оптимизации».
🔥217🎉6👏1🤣1
C++ enum class: безопасно, но местами раздражает

enum class даёт строгую типизацию и не позволяет случайно смешивать значения с обычными числами.

Но есть нюанс: даже если enum используется как набор флагов,


Flags::Read | Flags::Write


не скомпилируется.

Для |, &, ^, ~ придётся вручную определить операторы и приводить значения к базовому типу.

Это правильное поведение с точки зрения type safety, но бойлерплейта становится заметно больше.

Поэтому в некоторых C++-проектах для битовых флагов до сих пор используют обычный enum внутри namespace: меньше защиты, зато код значительно проще.
11👍7🔥4
LEA в x86 выглядит как инструкция для адресов, но компиляторы часто используют её как скрытый калькулятор.

Формально LEA считает адрес без обращения к памяти:


lea eax, [rdi + 3]


Но по факту это обычная арифметика:


return x + 3;


Ещё хитрее:


lea eax, [rdi + rdi*4]


Это уже:


return x * 5;


Почему так делают?

Потому что x86-адресация умеет base + index * scale + offset, а LEA позволяет использовать эту механику без чтения памяти.

Бонус: LEA не трогает флаги процессора, в отличие от add.

Красота C и asm в том, что за простой строкой x * 5 может стоять не mul, а маленький трюк архитектуры.
21🔥12❤‍🔥2
Оператор # в препроцессоре C превращает токены в строковые литералы ещё на этапе компиляции.

Никакого преобразования во время выполнения не происходит.

Ядро Linux использует этот трюк в макросах вроде WARN_ON(), чтобы вывести точное условие, которое не прошло проверку.

Вы пишете выражение один раз, а препроцессор автоматически генерирует соответствующую строку.

Один оператор - и ваши debug-сообщения остаются идеально синхронизированы с кодом.
❤‍🔥11🤷‍♂3🔥21
Четыре строки делают сложение `float` заметно точнее

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

Алгоритм Кэхэна хранит потерянную часть в отдельной переменной и компенсирует её на следующем шаге:


float kahanSum(const float *nums, int count)
{
float sum = 0.0f;
float correction = 0.0f;

for (int i = 0; i < count; ++i)
{
float adjusted = nums[i] - correction;
float next = sum + adjusted;

correction = (next - sum) - adjusted;
sum = next;
}

return sum;
}


Здесь correction запоминает ошибку округления, которая потерялась при предыдущем сложении.

Обычная сумма быстрее, но Kahan Summation полезен там, где важна численная точность:

- научные расчёты;
- статистика и аналитика;
- графика и симуляции;
- обработка больших массивов;
- накопление очень маленьких значений рядом с большими.

Метод предложил Уильям Кэхэн в 1965 году. Небольшое усложнение цикла может заметно уменьшить ошибку без перехода на более тяжёлый числовой тип.
17🔥9❤‍🔥2
Лето, ИТ-Пикник и музыка известных артистов уже через несколько дней!

8 августа в Коломенском пройдет ИТ-Пикник.

В программе — выступления проекта LAB Антона Беляева, IOWA, Cream Soda, Pompeya, мартина и Совы.

А днем — научпоп-лекции, дискуссии об ИИ и больших языковых моделях, мастер-классы и интерактивы. Полезные знакомства и развлечения тоже будут.

Зарегистрироваться и узнать подробности можно на сайте мероприятия.

В билет входит +1 — можно позвать близких и друзей.

До встречи в месте притяжения ИТ.
16
Keylogger в несколько строк C? Почти.

На самом деле это не «магия взлома», а raw mode в терминале.

Обычно терминал ждёт Enter и сам обрабатывает ввод.
А здесь программа отключает echo и canonical mode, поэтому видит каждое нажатие сразу.

Именно так работают редакторы, TUI-приложения и терминальные игры.

Важно: использовать только на своём вводе и в учебных целях. Перехват чужих клавиш - уже не программирование, а нарушение безопасности.
👍13❤‍🔥5🔥42🥰1
⚡️ Генератор случайных чисел всего из трёх XOR и сдвигов

В 2003 году Джордж Марсалья представил xorshift - один из самых простых и быстрых генераторов псевдослучайных чисел.

Классический xorshift32:


uint32_t xorshift32(void)
{
state ^= state << 13;
state ^= state >> 17;
state ^= state << 5;
return state;
}


Фактически весь алгоритм:


shift → XOR
shift → XOR
shift → XOR


При ненулевом начальном state период может достигать:


2³² - 1


Никаких умножений, делений или тяжёлой математики, поэтому подобные RNG отлично подходят для игр, симуляций и procedural generation, где важна скорость.

Но есть нюанс: xorshift нельзя использовать для криптографии. Его внутреннее состояние можно предсказать, поэтому для ключей, паролей и токенов нужны криптографически стойкие генераторы.

Иногда действительно полезный алгоритм помещается буквально в три строки.

#Programming #Algorithms #C #Random
Please open Telegram to view this post
VIEW IN TELEGRAM
18🔥8👍2🥰1
⚡️ Один `static` - три разных смысла. Добро пожаловать в C.

В C ключевое слово static меняет поведение в зависимости от того, где именно оно написано.

### 1. static у глобальной переменной


static int global;


Переменная имеет internal linkage - она доступна только внутри текущего .c файла.

Это удобный способ спрятать детали реализации модуля.

### 2. static внутри функции


void foo(void) {
static int count;
count++;
}


count не создаётся заново при каждом вызове.

Он существует всё время работы программы и сохраняет значение между вызовами функции.


foo(); // count = 1
foo(); // count = 2
foo(); // count = 3


### 3. static у функции


static void bar(void) {
}


Функция становится видна только внутри текущего translation unit.

Другой .c файл вызвать bar() напрямую уже не сможет.

Итого:


static global variable -> скрыть символ внутри файла
static local variable -> сохранить состояние между вызовами
static function -> скрыть функцию внутри файла


🔥 Поэтому static в C полезнее воспринимать не как одно конкретное поведение, а как подсказку проверить две вещи:

lifetime и linkage.

#C #Programming #SystemsProgramming #LowLevel #Cpp
👍15🔥96❤‍🔥1
🎶 Оптимизированный аудиовизуализатор для Windows

Spectrum — это легковесный аудиовизуализатор на C++, который обрабатывает звук в реальном времени и выводит его в консоль без разрывов экрана. Он использует FFTW3 для анализа аудиосигналов и обеспечивает точное визуальное представление частот.

🚀 Основные моменты:
- Реализация на C++17 для Windows.
- Низкое использование CPU и памяти.
- Поддержка WASAPI для захвата системного звука.
- Отображение в виде ASCII-графиков.
- Легкий в использовании и установке.

📌 GitHub: https://github.com/majockbim/spectrum

#cpp
👍63🔥2