Так какой же самый быстрый способ разбить слово на два байта?
short s = 0x3210;
char c1 = s >> 8;
char c2 = s & 0x00ff;
против
short s = 0x3210;
char c1 = s >> 8;
char c2 = (s << 8) >> 8;
Как насчет
short s = 0x3210;
char* c = (char*)&s; // where c1 = c[0] and c2 = c[1]
Пусть компилятор сделает эту работу за вас. использование union
где байты будут разделены без каких-либо ручных сдвигов. Посмотрите на псевдокод:
union U {
short s; // or use int16_t to be more specific
// vs.
struct Byte {
char c1, c2; // or use int8_t to be more specific
}
byte;
};
Использование простое:
U u;
u.s = 0x3210;
std::cout << u.byte.c1 << " and " << u.byte.c2;
Концепция проста, после этого вы можете перегружать операторов, чтобы сделать их более интересными, если хотите.
Важно отметить, что в зависимости от вашего компилятора порядок c1
а также c2
может отличаться, но это будет известно до компиляции. Вы можете установить некоторые условные макросы, чтобы убедиться, что порядок соответствует вашим потребностям в любом компиляторе.
Я на 99,9% уверен, что первый из них, по крайней мере, так же быстр, как второй, почти во всех архитектурах. Могут быть некоторые архитектуры, где это не имеет никакого значения (они равны), и в некоторых архитектурах последняя будет медленнее.
Основная причина, по которой я бы сказал, что вторая медленнее, состоит в том, что есть две смены c2
число. Процессор не может начать обрабатывать вторую смену, пока не выполнит первую смену.
Кроме того, компилятор вполне может быть в состоянии сделать другие умные вещи с первым (если есть инструкции для этого — например, процессор x86 может загрузить s
в AX, и сохранить AL в c1
и ах в c2
— никаких дополнительных инструкций помимо операции сохранения), где вторая гораздо менее вероятно будет «известным общим шаблоном» (я, конечно, никогда не видел, чтобы этот вариант использовался в коде, где shift/and
этот метод используется очень часто — часто в «пиксельных циклах», что означает, что для него важно реализовать хорошую оптимизацию).
Как всегда, измерить, измерить и снова измерить. И если вы не заинтересованы ТОЛЬКО в производительности вашей конкретной машины, попробуйте ее на разных моделях / производителях процессоров, чтобы вы не делали что-то на 5% быстрее на вашей модели машины, но на 20% медленнее на другой модели.
Вы должны использовать бросок, а не маску или две смены, чтобы извлечь младший байт. Затем компилятор сделает все, что он знает, чтобы быть самым быстрым. Это оставляет вас с битом старшего разряда, для которого есть только один выбор.
Вы должны время каждого из них в for (long i = 0; i < 100000000; i++)
, Я сделал, и быстрее был 1-й (0,82 с 0,84 с). Самый простой способ сделать это в MVS — установить часы на @clk
,