C
C++ Academy
16.07.2026 12:45 · 👁 1.1K
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.
C
C++ Academy
14.07.2026 13:01 · 👁 1.7K
C++23 добавил `std::expected`, и это одна из самых практичных вещей в языке за последние годы.
Идея простая: функция возвращает либо нормальный результат, либо ошибку. Без исключений, без output-параметров и без неявного control flow, который потом сложно отследить.
Например, парсер заголовка может вернуть uint32_t, если всё хорошо, или std::error_code, если буфер слишком короткий. Вызывающая сторона сразу видит: здесь результат может быть ошибкой, её нельзя «случайно забыть» так же легко, как при старом стиле с кодами возврата.
Это особенно удобно для системного кода, сетевых протоколов, парсеров, embedded и всего, где исключения либо запрещены, либо нежелательны.
std::expected не делает обработку ошибок магической. Он просто заставляет контракт функции быть честным: успешный результат и возможная ошибка описаны прямо в типе.
C
C++ Academy
13.07.2026 09:03 · 👁 1.8K
🚀 Anthropic выложили reference harness для поиска и исправления уязвимостей с Claude
Очень недооценённый репозиторий для defensive security.
Идея простая: Claude проходит полный цикл работы с уязвимостью:
* threat model
* поиск подозрительных мест
* проверка
* triage
* отчёт
* патч
Внутри есть Claude Code skills вроде /vuln-scan, /triage и /patch, которые можно запускать интерактивно.
Есть и автономный harness: можно настроить цель, ограничения и дать агенту самому пройти цикл анализа.
https://github.com/anthropics/defending-code-reference-harness
C
C++ Academy
12.07.2026 13:02 · 👁 1.8K
⚡️ Почему обычный `min(a, b)` в C может вернуть неожиданный результат
В C есть неприятная ловушка: если сравнивать signed и unsigned значения, компилятор может привести оба числа к unsigned.
И тогда отрицательное число внезапно превращается в огромное положительное.
Пример:
#define min(a, b) ((a) < (b) ? (a) : (b))
int x = -1;
unsigned int y = 10;
printf("%u\n", min(x, y));
Интуитивно кажется, что минимум — -1.
Но при сравнении x < y значение -1 приводится к unsigned и становится очень большим числом. В итоге сравнение работает уже не так, как ожидает разработчик.
Именно поэтому в Linux kernel макрос min() устроен хитрее. Он не просто сравнивает два значения, а сначала делает type check:
#define min(x, y) ({ \
typeof(x) _x = (x); \
typeof(y) _y = (y); \
(void) (&_x == &_y); \
_x < _y ? _x : _y; \
})
Ключевая строка здесь:
(void) (&_x == &_y);
Она заставляет компилятор проверить, что типы совместимы. Если один аргумент signed, а другой unsigned, такой код может превратиться в ошибку компиляции, а не в тихий баг в рантайме.
Это хороший пример системного C-подхода: лучше сломать сборку сразу, чем получить «правильный» код, который иногда считает неправильно.
В низкоуровневом коде такие мелочи решают очень много. Один неудачный implicit conversion — и проверка размера, индекса или лимита начинает работать против вас.
C
C++ Academy
10.07.2026 12:59 · 👁 2K
C умел «объектный стиль» задолго до модных споров про ООП.
В Linux-драйверах это видно особенно хорошо. Каждый драйвер фактически реализует интерфейс, просто заполняя структуру с указателями на функции.
file_operations из include/linux/fs.h - хороший пример. Ядро говорит: вот набор операций, которые может поддерживать файл, сокет или устройство. Драйвер сам решает, какие обработчики дать:
open
read
write
release
mmap
fsync
unlocked_ioctl
Если операция не нужна, поле остаётся NULL, и ядро использует поведение по умолчанию там, где это возможно.
По сути это тот же контракт между системой и реализацией, только без классов, наследования и рантаймовой магии. Есть таблица функций, есть объект, есть набор действий, которые с ним можно выполнить.
Именно поэтому C до сих пор живёт в ядрах, драйверах и системном коде. Он не навязывает модель абстракций, но даёт достаточно низкоуровневых инструментов, чтобы собрать нужную модель самому.
Просто вместо красивого слова interface у тебя struct с function pointers.
#programming #linux #c
C
C++ Academy
08.07.2026 12:02 · 👁 2.4K
Один из самых дорогих багов в истории Debian начался с «невинной» правки.
В OpenSSL были строки, которые выглядели странно: код подмешивал в генератор случайных чисел неинициализированную память.
Статические анализаторы и Valgrind ругались на это как на ошибку.
Мейнтейнер решил убрать предупреждение и удалил две строки.
На вид - чистка мусора.
По факту - генератор случайных чисел потерял важный источник энтропии.
И почти два года Debian OpenSSL выпускал предсказуемые ключи.
Пострадали SSL-сертификаты, SSH-ключи, VPN, серверы и всё, что зависело от нормальной криптографической случайности.
Урок жёсткий: в security-коде странная строка не всегда мусор.
Иногда это защита, которую нельзя трогать без понимания всей модели угроз.
C
C++ Academy
04.07.2026 12:03 · 👁 3.6K
Красота C в том, что он почти не прячет механику компьютера.
Хочешь понять, как копируется файл? Не нужен огромный фреймворк. Достаточно посмотреть на простой C-код:
• открыть исходный файл через fopen
• открыть файл назначения
• выделить буфер через malloc
• читать кусками через fread
• записывать через fwrite
• освободить память и закрыть файлы
Всё честно и прямо: байты читаются из одного места и записываются в другое.
Именно поэтому C до сих пор так важен. Он не всегда самый удобный, но он показывает, что реально происходит под капотом.
После такого начинаешь лучше понимать не только язык, а саму систему.
C
C++ Academy
04.07.2026 11:01 · 👁 2.7K
🚀 SIMD-ускоренное преобразование целых чисел в строки
Simditoa - библиотека для быстрого преобразования 64-битных целых чисел в десятичные строки с использованием SIMD-инструкций. Достигает скорости менее 2 наносекунд на современном оборудовании, обеспечивая высокую производительность на архитектурах x86-64.
🚀 Основные моменты:
- Поддержка AVX-512 для максимальной скорости.
- Альтернативная скалярная реализация для совместимости.
- Простой API для интеграции в проекты C++.
- Значительное ускорение по сравнению с std::to_chars.
📌 GitHub: https://github.com/simditoa/simditoa
#cpp
C
C++ Academy
02.07.2026 13:15 · 👁 2.8K
Godot фактически запрещает vibe coding в контрибуциях.
Причина простая: PR стало легче генерировать, но не легче проверять. Для open-source движка каждый патч всё равно должен разобрать мейнтейнер, который понимает архитектуру, риски и последствия изменений.
Теперь автономные агенты, крупные AI-сгенерированные куски кода и сгенерированный текст в issues, proposals и PR-дискуссиях запрещены. Разрешены только мелкие помощники вроде автодополнения, regex и find/replace. Помощь AI в коде нужно раскрывать.
На практике правило будет сложно применять: почти невозможно наверняка доказать, где был vibe coding, а где обычная работа разработчика.
Godot защищает не стиль разработки, а время ревьюеров. Код можно сгенерировать за минуты, но ответственность за него всё равно остаётся на людях.
godotengine.org/article/contribution-policy-2026/
C
C++ Academy
02.07.2026 12:04 · 👁 2.2K
volatile в C нужен не «для красоты», а чтобы компилятор не сломал работу с железом.
Когда код читает memory-mapped IO регистр, значение может измениться не из-за программы, а из-за устройства.
Например:
#define STATUS_REG (*(volatile uint32_t*)0x40000000)
#define READY_BIT (1 << 0)
while (!(STATUS_REG & READY_BIT)) {
// ждём, пока железо станет ready
}
Без volatile компилятор может решить:
«Значение не меняется внутри цикла, значит можно прочитать один раз».
И всё. Опрос регистра превращается в бесконечный цикл или вообще оптимизируется не так, как вы ожидали.
Главная мысль:
volatile говорит компилятору:
это значение может измениться вне твоего контроля, не трогай чтения и записи.
Важно: volatile не заменяет mutex, atomics и memory barriers. Но для MMIO-регистров это база, без которой embedded-код может вести себя как магия из ада.