Как объяснил Александру, вам нужно очистить поле битов, которое вы пытаетесь установить, прежде чем приступить к его установке.
Просто добавьте дополнительный комментарий о том, почему ваш код не сделал того, что вы хотели, рассмотрим, что происходит с переменной на двоичном уровне:
row |= 0x2 << 4;
Оператор | = является «побитовым или». Следовательно, если либо бит, который вы пытаетесь установить, ИЛИ передаваемый бит, установлен на 1, результат равен 1. В вашем коде строка установлена на 0x33333333, поэтому каждый 4-битный шестнадцатеричный цифра 0011 в двоичном виде. Когда вы поразрядно или что с 0x2 , вы получите 0x3:
/* 0x3 | 0x2 = 0x3 */
0011 | 0010 = 0011
Если вы сначала очистите битовое поле, вы получите 0x2, что вам нужно:
/* 0x3 | 0x0 = 0x0 */
0011 | 0000 = 0000
/* 0x0 | 0x2 = 0x2 */
0000 | 0010 = 0010
Обратите внимание, что манипулирование данными с использованием сдвигов и побитовых операций вряд ли будет переносимым между различными платформами. Вы можете столкнуться с проблемами, пытаясь выполнить код, основанный на битовых сдвигах, на машинах с различным порядком байтов или даже если вы попытаетесь запустить код, который работает на 32-битной машине на 64-битной машине:
http://www.viva64.com/en/a/0004/#ID0EQFDI
В Википедии есть больше побитовых операций:
http://en.wikipedia.org/wiki/Bitwise_operation