C++ Academy
описание
По всем вопросам- @workakkk РКН: clck.ru/3FmxJF #VRHSZ
15 470
подписчиков
Охват к подписчикам
15,6%
ERR
Реакции к просмотрам
0,51%
772 на 50 постов
Пересылки к просмотрам
1,00%
1 509
Постов в день
0,7
всего 101
Где отзываются чаще
доля реакций к просмотрам- 5 авг.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, а маленький трюк архитектуры.1,71%
- 12 авг.💡 Clang умеет показывать AST, и это один из лучших способов реально понять, что компилятор видит в вашем C/C++ коде. AST — это Abstract Syntax Tree, внутреннее представление программы после парсинга. Например, простой код: int x = a + b * 2; для компилятора — не просто строка текста, а дерево примерно такого смысла: VarDecl └── BinaryOperator + ├── a └── BinaryOperator * ├── b └── 2 Именно через такое представление компилятор понимает структуру выражений, типы, области видимости и то, какие преобразования можно выполнить дальше. У Clang AST можно получить напрямую: clang++ -Xclang -ast-dump -fsyntax-only main.cpp А в Compiler Explorer / Godbolt есть отдельный режим просмотра AST, поэтому можно менять код и сразу видеть, как перестраивается дерево. Особенно полезно разбирать так: * шаблоны; * перегрузку функций; * implicit conversions; * auto; * лямбды; * range-based for; * временные объекты; * разные формы инициализации. Если регулярно смотреть AST, C++ постепенно перестаёт выглядеть как набор «магических правил». Начинаешь видеть код примерно так, как его видит компилятор. 🔗 https://godbolt.org/z/cfc7h41bT #Cpp #Clang #Compiler #Programming1,58%
- 6 авг.Четыре строки делают сложение `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 году. Небольшое усложнение цикла может заметно уменьшить ошибку без перехода на более тяжёлый числовой тип.1,35%
- 2 авг.Doom в 1993 работал на 486 и 4 МБ RAM. А современные игры почему едят 16 ГБ? Секрет был в BSP-дереве: уровень заранее делился на области, а движок во время рендера просто обходил дерево в нужном порядке. Без z-buffer, без лишней магии, без пересчёта видимости с нуля каждый кадр. Кармак буквально заставил геометрию работать вместо железа. Подписывайся, тут ещё много таких историй про код, который унижает современные «оптимизации».1,31%
- 9 авг.⚡️ Один `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 #Cpp1,26%
- 15:03⚙️ Обычный strcat() в цикле может незаметно превратить простую склейку строк в O(n²). Причина в том, что strcat() при каждом вызове сначала ищет конец уже собранной строки. Чем длиннее буфер, тем больше данных приходится повторно проходить. Например: for (int i = 0; i < 100000; i++) strcat(buf, "chunk"); В бенчмарке сборка строки примерно на 1 МБ заняла около 4,1 секунды. Если же заранее выделить буфер и просто хранить текущую позицию записи: char *p = buf; for (int i = 0; i < 100000; i++) { memcpy(p, "chunk", 5); p += 5; } тот же объём собирается примерно за 0,4 мс. Разница больше чем в 10 000 раз. Мелочь, которую легко пропустить: проблема не в копировании строки, а в постоянном повторном поиске её конца.1,24%
- 8 авг.⚡️ Генератор случайных чисел всего из трёх 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 #Random1,24%
- 6 авг.Keylogger в несколько строк C? Почти. На самом деле это не «магия взлома», а raw mode в терминале. Обычно терминал ждёт Enter и сам обрабатывает ввод. А здесь программа отключает echo и canonical mode, поэтому видит каждое нажатие сразу. Именно так работают редакторы, TUI-приложения и терминальные игры. Важно: использовать только на своём вводе и в учебных целях. Перехват чужих клавиш - уже не программирование, а нарушение безопасности.1,23%
- 16 авг.⚡️ Fenwick Tree держится на одном битовом трюке Fenwick Tree, или Binary Indexed Tree, считает prefix sums за O(log n). Вся магия в операции: i & -i Она находит младший установленный бит числа. Почему это работает? В two’s complement число -i получается как инверсия битов i плюс 1. Когда мы делаем i & -i, остаётся только самый правый бит, равный 1. Например: i = 12 // 1100 -i // 0100 в нужной маске i & -i = 4 Именно это значение говорит Fenwick Tree, на сколько нужно прыгнуть по индексам. Для обновления: for (; i < MAXN; i += i & -i) tree[i] += v; Мы идём вверх по структуре и обновляем все узлы, которые покрывают этот индекс. Для запроса суммы: for (; i > 0; i -= i & -i) s += tree[i]; Мы идём вниз и собираем нужные блоки суммы. Одна и та же операция управляет двумя направлениями: * i += i & -i — перейти к следующему ответственному узлу * i -= i & -i — убрать последний блок из prefix sum Поэтому Fenwick Tree такой компактный: никаких явных рёбер, указателей и рекурсии. Только массив и битовая арифметика. Красота структуры в том, что дерево как бы спрятано внутри двоичного представления индекса.1,11%
- 10 июл.C умел «объектный стиль» задолго до модных споров про ООП. В Linux-драйверах это видно особенно хорошо. Каждый драйвер фактически реализует интерфейс, просто заполняя структуру с указателями на функции. file_operations из include/linux/fs.h - хороший пример. Ядро говорит: вот набор операций, которые может поддерживать файл, сокет или устройство. Драйвер сам решает, какие обработчики дать: open read write release mmap fsync unlocked_ioctl Если операция не нужна, поле остаётся NULL, и ядро использует поведение по умолчанию там, где это возможно. По сути это тот же контракт между системой и реализацией, только без классов, наследования и рантаймовой магии. Есть таблица функций, есть объект, есть набор действий, которые с ним можно выполнить. Именно поэтому C до сих пор живёт в ядрах, драйверах и системном коде. Он не навязывает модель абстракций, но даёт достаточно низкоуровневых инструментов, чтобы собрать нужную модель самому. Просто вместо красивого слова interface у тебя struct с function pointers. #programming #linux #c1,02%
- 14 авг.📚 Библиотека для работы с SQLite в C++26 с использованием рефлексии Reflite — это библиотека на C++26, которая упрощает взаимодействие с SQLite, позволяя использовать обычные структуры как основу для выполнения запросов. Она поддерживает основные операции: вставка, удаление, выборка и обновление, избавляя от лишнего шаблона кода. 🚀 Основные моменты: - Легковесная библиотека в одном файле - Поддержка операций INSERT, DELETE, SELECT, UPDATE - Использует рефлексию для работы с типами структур - Не требует полной реализации SQL, фокус на простоте - Совместима с современными компиляторами C++26 📌 GitHub: https://github.com/KaruroChori/reflite #cpp0,94%
- 6 авг.Оператор # в препроцессоре C превращает токены в строковые литералы ещё на этапе компиляции. Никакого преобразования во время выполнения не происходит. Ядро Linux использует этот трюк в макросах вроде WARN_ON(), чтобы вывести точное условие, которое не прошло проверку. Вы пишете выражение один раз, а препроцессор автоматически генерирует соответствующую строку. Один оператор - и ваши debug-сообщения остаются идеально синхронизированы с кодом.0,91%