Учебные материалы: механизм вместо тезисов, блоки «Факты для карточек», Ловушки (Claude Code) + diag/cards_src.tsv
This commit is contained in:
@@ -8,19 +8,26 @@
|
||||
протоколах.
|
||||
- **Почему это в Eltex:** заголовки пакетов, маски, флаги, регистры — всё битовое. Вопросы
|
||||
вида «посчитай единичные биты» и «поменяй порядок байт» на собеседовании почти гарантированы.
|
||||
На практике `bswap` нужен ровно потому, что сеть передаёт многобайтовые поля в network byte
|
||||
order (big-endian), а x86 внутри — little-endian: без разворота байт число читается неверно.
|
||||
- **Что сдаётся:** `solution.cpp`, проходящий `python3 grade.py 01`.
|
||||
|
||||
## Глава II. Что нужно знать до старта
|
||||
|
||||
Четыре инструмента, которых достаточно:
|
||||
|
||||
1. `x & (x - 1)` — гасит самый младший единичный бит. Отсюда классика: число единиц можно
|
||||
считать циклом, пока `x` не станет нулём.
|
||||
1. `x & (x - 1)` — гасит самый младший единичный бит. Механизм: в дополнительном коде `x - 1`
|
||||
переворачивает все нули справа от младшего единичного бита в единицы, а сам этот бит — в ноль,
|
||||
биты выше не трогает; операция `&` с исходным `x` поэтому обнуляет ровно один бит — младший
|
||||
единичный. Отсюда классика: число единиц можно считать циклом, пока `x` не станет нулём, и
|
||||
число итераций равно числу единичных бит, а не 32.
|
||||
2. `x & 1` — младший бит; `x >> 1` — сдвиг вправо.
|
||||
3. `x & (1u << k)` — проверка k-го бита.
|
||||
4. Маски: `0x000000FF`, `0x0000FF00`, `0x00FF0000`, `0xFF000000` — это четыре байта 32-битного
|
||||
числа. Комбинация «сдвинул и сложил» даёт любой порядок байт.
|
||||
|
||||
Почему дальше: та же логика масок и сдвигов нужна в задаче 04 — разбор IPv4-заголовка byte-по-byte.
|
||||
|
||||
## Глава III. Задание
|
||||
|
||||
Реализуй в `solution.cpp` четыре функции. Встроенные `__builtin_popcount`, `std::popcount`,
|
||||
@@ -83,12 +90,25 @@ uint32_t bswap32(uint32_t x); // поменять порядок ба
|
||||
Если перепутать — биты уедут на одну позицию.
|
||||
</details>
|
||||
|
||||
## Глава VII. Частые ошибки
|
||||
## Глава VII. Ловушки
|
||||
|
||||
- Сдвиги в `int` вместо `uint32_t` → UB, UBSAN ругается.
|
||||
- Забыт ноль в `is_power_of_two`.
|
||||
- В `bswap32` перепутаны направления сдвигов (влево/вправо) — проверь на `0x11223344`.
|
||||
- Использование `__builtin_popcount` — запрещено условием: смысл в том, чтобы написать самому.
|
||||
- Сдвиги в `int` вместо `uint32_t` → сдвиг `1 << 31` для знакового типа — UB → UBSAN падает
|
||||
на этой строке с диагностикой конкретного сдвига.
|
||||
- Забыт ноль в `is_power_of_two` → `0 & (0 - 1) == 0`, функция возвращает `true` на нуле →
|
||||
тест на `x == 0` красный.
|
||||
- В `bswap32` перепутаны направления сдвигов (влево/вправо) → байты встают не на свои места →
|
||||
`bswap32(0x11223344) != 0x44332211`, видно прямым сравнением.
|
||||
- Использование `__builtin_popcount` — запрещено условием: смысл в том, чтобы написать самому;
|
||||
формально тест это не всегда ловит по выводу, но нарушает условие задачи.
|
||||
|
||||
**Факты для карточек**
|
||||
- base | Сколько байт меняет местами `bswap32`? — 4
|
||||
- core | Что делает `x & (x - 1)`? — гасит младший единичный бит `x`
|
||||
- core | Сколько итераций цикла `popcount32` на `x = 0xFFFFFFFF`? — 32 (по числу единичных бит)
|
||||
- deep | Почему `1u << 31` пишут с суффиксом `u`, а не как `int`? — сдвиг знакового `int` в
|
||||
знаковый бит — UB, `uint32_t` определён стандартом для любых сдвигов в пределах разрядности
|
||||
- base | Какой порядок байт использует сеть для многобайтовых полей? — network byte order
|
||||
(big-endian)
|
||||
|
||||
## После сдачи
|
||||
|
||||
|
||||
Reference in New Issue
Block a user