Вы находитесь на странице: 1из 6

Краткое оглавление

1 Образцы кода 1

2 Важные фундаментальные вещи 437

3 Более сложные примеры 459

4 Java 638

5 Поиск в коде того что нужно 677

6 Специфичное для ОС 713

7 Инструменты 768

8 Примеры из практики 771

9 Примеры разбора закрытых (proprietary) форматов файлов 910

10 Прочее 973

11 Что стоит почитать 987

12 Сообщества 990

Послесловие 992

Приложение 994

Список принятых сокращений 1023

Глоссарий 1028

Предметный указатель 1030

iii
ОГЛАВЛЕНИЕ

Оглавление

1 Образцы кода 1
1.1 Метод . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1
1.2 Некоторые базовые понятия . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2
1.2.1 Краткое введение в CPU . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2
1.2.2 Представление чисел . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3
1.3 Пустая функция . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5
1.3.1 x86 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5
1.3.2 ARM . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6
1.3.3 MIPS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6
1.3.4 Пустые функции на практике . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6
1.4 Возврат значения . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7
1.4.1 x86 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7
1.4.2 ARM . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8
1.4.3 MIPS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8
1.4.4 На практике . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8
1.5 Hello, world! . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9
1.5.1 x86 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9
1.5.2 x86-64 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14
1.5.3 GCC — ещё кое-что . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18
1.5.4 ARM . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19
1.5.5 MIPS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25
1.5.6 Вывод . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 29
1.5.7 Упражнения . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30
1.6 Пролог и эпилог функций . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30
1.6.1 Рекурсия . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30
1.7 Стек . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30
1.7.1 Почему стек растет в обратную сторону? . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31
1.7.2 Для чего используется стек? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31
1.7.3 Разметка типичного стека . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38
1.7.4 Мусор в стеке . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38
1.7.5 Упражнения . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 42
1.8 printf() с несколькими аргументами . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 42
1.8.1 x86 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 42
1.8.2 ARM . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 53
1.8.3 MIPS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 59
1.8.4 Вывод . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 65
1.8.5 Кстати . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 66
1.9 scanf() . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 66
1.9.1 Простой пример . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 66
1.9.2 Глобальные переменные . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 75
1.9.3 Проверка результата scanf() . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 85
1.9.4 Упражнение . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 97
1.10 Доступ к переданным аргументам . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 98
1.10.1 x86 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 98
1.10.2 x64 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 100
1.10.3 ARM . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 103
1.10.4 MIPS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 106
1.11 Ещё о возвращаемых результатах . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 107
1.11.1 Попытка использовать результат функции возвращающей void . . . . . . . . . . . . 107
1.11.2 Что если не использовать результат функции? . . . . . . . . . . . . . . . . . . . . . . . 108
1.11.3 Возврат структуры . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 109
1.12 Указатели . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 110
1.13 Оператор GOTO . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 110

iv
ОГЛАВЛЕНИЕ
1.13.1 Мертвый код . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 113
1.13.2 Упражнение . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 114
1.14 Условные переходы . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 114
1.14.1 Простой пример . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 114
1.14.2 Вычисление абсолютной величины . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 131
1.14.3 Тернарный условный оператор . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 133
1.14.4 Поиск минимального и максимального значения . . . . . . . . . . . . . . . . . . . . . . 136
1.14.5 Вывод . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 141
1.14.6 Упражнение . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 142
1.15 switch()/case/default . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 142
1.15.1 Если вариантов мало . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 142
1.15.2 И если много . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 156
1.15.3 Когда много case в одном блоке . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 168
1.15.4 Fall-through . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 172
1.15.5 Упражнения . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 174
1.16 Циклы . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 174
1.16.1 Простой пример . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 174
1.16.2 Функция копирования блоков памяти . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 185
1.16.3 Проверка условия . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 188
1.16.4 Вывод . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 189
1.16.5 Упражнения . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 190
1.17 Еще кое-что о строках . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 190
1.17.1 strlen() . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 190
1.18 Замена одних арифметических инструкций на другие . . . . . . . . . . . . . . . . . . . . . . 202
1.18.1 Умножение . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 202
1.18.2 Деление . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 207
1.18.3 Упражнение . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 208
1.19 Работа с FPU . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 208
1.19.1 IEEE 754 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 208
1.19.2 x86 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 208
1.19.3 ARM, MIPS, x86/x64 SIMD . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 209
1.19.4 Си/Си++ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 209
1.19.5 Простой пример . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 209
1.19.6 Передача чисел с плавающей запятой в аргументах . . . . . . . . . . . . . . . . . . . 220
1.19.7 Пример со сравнением . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 223
1.19.8 Некоторые константы . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 257
1.19.9 Копирование . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 257
1.19.10 Стек, калькуляторы и обратная польская запись . . . . . . . . . . . . . . . . . . . . . 257
1.19.11 80 бит? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 257
1.19.12 x64 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 257
1.19.13 Упражнения . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 258
1.20 Массивы . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 258
1.20.1 Простой пример . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 258
1.20.2 Переполнение буфера . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 265
1.20.3 Защита от переполнения буфера . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 273
1.20.4 Еще немного о массивах . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 276
1.20.5 Массив указателей на строки . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 277
1.20.6 Многомерные массивы . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 284
1.20.7 Набор строк как двухмерный массив . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 291
1.20.8 Вывод . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 295
1.21 Кстати . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 295
1.21.1 Упражнения . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 295
1.22 Работа с отдельными битами . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 295
1.22.1 Проверка какого-либо бита . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 295
1.22.2 Установка и сброс отдельного бита . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 299
1.22.3 Сдвиги . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 308
1.22.4 Установка и сброс отдельного бита: пример с FPU1 . . . . . . . . . . . . . . . . . . . . 308
1.22.5 Подсчет выставленных бит . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 312
1.22.6 Вывод . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 327
1.22.7 Упражнения . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 329
1.23 Линейный конгруэнтный генератор . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 329
1.23.1 x86 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 330
1.23.2 x64 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 331
1 Floating-Point Unit

v
ОГЛАВЛЕНИЕ
1.23.3 32-bit ARM . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 332
1.23.4 MIPS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 332
1.23.5 Версия этого примера для многопоточной среды . . . . . . . . . . . . . . . . . . . . . . 335
1.24 Структуры . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 335
1.24.1 MSVC: Пример SYSTEMTIME . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 335
1.24.2 Выделяем место для структуры через malloc() . . . . . . . . . . . . . . . . . . . . . . . . 339
1.24.3 UNIX: struct tm . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 340
1.24.4 Упаковка полей в структуре . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 350
1.24.5 Вложенные структуры . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 357
1.24.6 Работа с битовыми полями в структуре . . . . . . . . . . . . . . . . . . . . . . . . . . . . 360
1.24.7 Упражнения . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 367
1.25 Объединения (union) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 367
1.25.1 Пример генератора случайных чисел . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 367
1.25.2 Вычисление машинного эпсилона . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 372
1.25.3 Быстрое вычисление квадратного корня . . . . . . . . . . . . . . . . . . . . . . . . . . . . 373
1.26 Указатели на функции . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 374
1.26.1 MSVC . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 375
1.26.2 GCC . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 382
1.26.3 Опасность указателей на ф-ции . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 386
1.27 64-битные значения в 32-битной среде . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 386
1.27.1 Возврат 64-битного значения . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 386
1.27.2 Передача аргументов, сложение, вычитание . . . . . . . . . . . . . . . . . . . . . . . . . 387
1.27.3 Умножение, деление . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 391
1.27.4 Сдвиг вправо . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 394
1.27.5 Конвертирование 32-битного значения в 64-битное . . . . . . . . . . . . . . . . . . . . 395
1.28 SIMD . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 396
1.28.1 Векторизация . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 397
1.28.2 Реализация strlen() при помощи SIMD . . . . . . . . . . . . . . . . . . . . . . . . . . . . 407
1.29 64 бита . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 410
1.29.1 x86-64 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 410
1.29.2 ARM . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 417
1.29.3 Числа с плавающей запятой . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 417
1.29.4 Критика 64-битной архитектуры . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 417
1.30 Работа с числами с плавающей запятой (SIMD) . . . . . . . . . . . . . . . . . . . . . . . . . . . . 418
1.30.1 Простой пример . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 418
1.30.2 Передача чисел с плавающей запятой в аргументах . . . . . . . . . . . . . . . . . . . 425
1.30.3 Пример со сравнением . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 426
1.30.4 Вычисление машинного эпсилона: x64 и SIMD . . . . . . . . . . . . . . . . . . . . . . . . 428
1.30.5 И снова пример генератора случайных чисел . . . . . . . . . . . . . . . . . . . . . . . . 429
1.30.6 Итог . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 430
1.31 Кое-что специфичное для ARM . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 430
1.31.1 Знак номера (#) перед числом . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 430
1.31.2 Режимы адресации . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 430
1.31.3 Загрузка констант в регистр . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 431
1.31.4 Релоки в ARM64 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 433
1.32 Кое-что специфичное для MIPS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 434
1.32.1 Загрузка 32-битной константы в регистр . . . . . . . . . . . . . . . . . . . . . . . . . . . 434
1.32.2 Книги и прочие материалы о MIPS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 436

2 Важные фундаментальные вещи 437


2.1 Целочисленные типы данных . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 438
2.1.1 Бит . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 438
2.1.2 Ниббл AKA nibble AKA nybble . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 438
2.1.3 Байт . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 439
2.1.4 Wide char . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 440
2.1.5 Знаковые целочисленные и беззнаковые . . . . . . . . . . . . . . . . . . . . . . . . . . . . 440
2.1.6 Слово (word) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 440
2.1.7 Регистр адреса . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 441
2.1.8 Числа . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 442
2.2 Представление знака в числах . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 444
2.2.1 Использование IMUL вместо MUL . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 445
2.2.2 Еще кое-что о дополнительном коде . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 446
2.3 Целочисленное переполнение (integer overflow) . . . . . . . . . . . . . . . . . . . . . . . . . . . . 447
2.4 AND . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 448

vi
ОГЛАВЛЕНИЕ
2.4.1 Проверка того, находится ли значение на границе 2n . . . . . . . . . . . . . . . . . . . . 448
2.4.2 Кирилличная кодировка KOI-8R . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 448
2.5 И и ИЛИ как вычитание и сложение . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 449
2.5.1 Текстовые строки в ПЗУ2 ZX Spectrum . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 449
2.6 XOR (исключающее ИЛИ) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 452
2.6.1 Бытовая речь . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 452
2.6.2 Шифрование . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 452
2.6.3 RAID3 4 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 452
2.6.4 Алгоритм обмена значений при помощи исключающего ИЛИ . . . . . . . . . . . . . . 452
2.6.5 Список связанный при помощи XOR . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 453
2.6.6 Хэширование Зобриста / табуляционное хэширование . . . . . . . . . . . . . . . . . . . 453
2.6.7 Кстати . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 454
2.6.8 AND/OR/XOR как MOV . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 454
2.7 Подсчет бит . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 454
2.8 Endianness (порядок байт) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 455
2.8.1 Big-endian (от старшего к младшему) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 455
2.8.2 Little-endian (от младшего к старшему) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 455
2.8.3 Пример . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 455
2.8.4 Bi-endian (переключаемый порядок) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 456
2.8.5 Конвертирование . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 456
2.9 Память . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 456
2.10 CPU . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 457
2.10.1 Предсказатели переходов . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 457
2.10.2 Зависимости между данными . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 457
2.11 Хеш-функции . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 457
2.11.1 Как работает односторонняя функция? . . . . . . . . . . . . . . . . . . . . . . . . . . . . 458

3 Более сложные примеры 459


3.1 Двойное отрицание . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 459
3.2 Пример strstr() . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 460
3.3 Конвертирование температуры . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 460
3.3.1 Целочисленные значения . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 460
3.3.2 Числа с плавающей запятой . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 462
3.4 Числа Фибоначчи . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 464
3.4.1 Пример #1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 465
3.4.2 Пример #2 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 468
3.4.3 Итог . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 471
3.5 Пример вычисления CRC32 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 472
3.6 Пример вычисления адреса сети . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 475
3.6.1 calc_network_address() . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 476
3.6.2 form_IP() . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 477
3.6.3 print_as_IP() . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 478
3.6.4 form_netmask() и set_bit() . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 479
3.6.5 Итог . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 480
3.7 Циклы: несколько итераторов . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 480
3.7.1 Три итератора . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 481
3.7.2 Два итератора . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 481
3.7.3 Случай Intel C++ 2011 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 483
3.8 Duff’s device . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 484
3.8.1 Нужно ли использовать развернутые циклы? . . . . . . . . . . . . . . . . . . . . . . . . . 487
3.9 Деление используя умножение . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 487
3.9.1 x86 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 487
3.9.2 Как это работает . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 489
3.9.3 ARM . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 489
3.9.4 MIPS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 490
3.9.5 Упражнение . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 491
3.10 Конверсия строки в число (atoi()) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 491
3.10.1 Простой пример . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 491
3.10.2 Немного расширенный пример . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 495
3.10.3 Упражнение . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 497
3.11 Inline-функции . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 498
3.11.1 Функции работы со строками и памятью . . . . . . . . . . . . . . . . . . . . . . . . . . . . 498
2 Постоянное запоминающее устройство
3 Redundant Array of Independent Disks

vii
ОГЛАВЛЕНИЕ
3.12 C99 restrict . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 506
3.13 Функция abs() без переходов . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 509
3.13.1 Оптимизирующий GCC 4.9.1 x64 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 509
3.13.2 Оптимизирующий GCC 4.9 ARM64 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 510
3.14 Функции с переменным количеством аргументов . . . . . . . . . . . . . . . . . . . . . . . . . . 510
3.14.1 Вычисление среднего арифметического . . . . . . . . . . . . . . . . . . . . . . . . . . . . 510
3.14.2 Случай с функцией vprintf() . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 514
3.14.3 Случай с Pin . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 515
3.14.4 Эксплуатация строки формата . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 515
3.15 Обрезка строк . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 516
3.15.1 x64: Оптимизирующий MSVC 2013 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 517
3.15.2 x64: Неоптимизирующий GCC 4.9.1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 519
3.15.3 x64: Оптимизирующий GCC 4.9.1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 520
3.15.4 ARM64: Неоптимизирующий GCC (Linaro) 4.9 . . . . . . . . . . . . . . . . . . . . . . . . . 521
3.15.5 ARM64: Оптимизирующий GCC (Linaro) 4.9 . . . . . . . . . . . . . . . . . . . . . . . . . . . 522
3.15.6 ARM: Оптимизирующий Keil 6/2013 (Режим ARM) . . . . . . . . . . . . . . . . . . . . . . 523
3.15.7 ARM: Оптимизирующий Keil 6/2013 (Режим Thumb) . . . . . . . . . . . . . . . . . . . . . 523
3.15.8 MIPS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 524
3.16 Функция toupper() . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 525
3.16.1 x64 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 526
3.16.2 ARM . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 527
3.16.3 Используя битовые операции . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 529
3.16.4 Итог . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 529
3.17 Обфускация . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 530
3.17.1 Текстовые строки . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 530
3.17.2 Исполняемый код . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 530
3.17.3 Виртуальная машина / псевдо-код . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 532
3.17.4 Еще кое-что . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 532
3.17.5 Упражнение . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 532
3.18 Си++ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 533
3.18.1 Классы . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 533
3.18.2 ostream . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 549
3.18.3 References . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 550
3.18.4 STL . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 551
3.18.5 Память . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 584
3.19 Отрицательные индексы массивов . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 585
3.19.1 Адресация строки с конца . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 585
3.19.2 Адресация некоторого блока с конца . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 585
3.19.3 Массивы начинающиеся с 1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 586
3.20 Больше об указателях . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 588
3.20.1 Работа с адресами вместо указателей . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 588
3.20.2 Передача значений как указателей; тэггированные объединения . . . . . . . . . . 591
3.20.3 Издевательство над указателями в ядре Windows . . . . . . . . . . . . . . . . . . . . . 591
3.20.4 Нулевые указатели . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 596
3.20.5 Массив как аргумент функции . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 600
3.20.6 Указатель на функцию . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 600
3.20.7 Указатель как идентификатор объекта . . . . . . . . . . . . . . . . . . . . . . . . . . . . 601
3.21 Оптимизации циклов . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 602
3.21.1 Странная оптимизация циклов . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 602
3.21.2 Еще одна оптимизация циклов . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 603
3.22 Еще о структурах . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 605
3.22.1 Иногда вместо массива можно использовать структуру в Си . . . . . . . . . . . . . . 605
3.22.2 Безразмерный массив в структуре Си . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 606
3.22.3 Версия структуры в Си . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 608
3.22.4 Файл с рекордами в игре «Block out» и примитивная сериализация . . . . . . . . . 609
3.23 memmove() и memcpy() . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 614
3.23.1 Анти-отладочный прием . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 615
3.24 setjmp/longjmp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 615
3.25 Другие нездоровые хаки связанные со стеком . . . . . . . . . . . . . . . . . . . . . . . . . . . . 617
3.25.1 Доступ к аргументам и локальным переменным вызывающей ф-ции . . . . . . . . 617
3.25.2 Возврат строки . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 619
3.26 OpenMP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 621
3.26.1 MSVC . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 623
3.26.2 GCC . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 625

viii

Вам также может понравиться