Это способ, которым я предпочитаю справляться с этим, "медленно". Это просто имеет больше смысла в моей голове. Кроме того, в отличие от маски и затем сдвига, не проблема в том, что >> расширяет знак (C / C ++ не является Java или C # в четкости там). Я исхожу из предположения, что 0 - это MSB (а всего 32 бита, хотя длинный может быть больше), как указано в вопросе.
long wxyz = ...; //(w = bits 0-8, x = bits 9-17 , y = bits 18-23, z = bits 24-29)
wxyz >>= 2; // discard 30-31 (or, really, "least two insignificant")
z = wzyz & 0x3f; // easy to see this is "6 bits", no?
wzyz >>= 6; // throw them out
y = wzyz & 0x3f;
wzyz >>= 6;
x = wzyz & 0x1ff;
wzyz >>= 9;
w = wzyz & 0x1ff;
wzyz >>= 9; // for fun, but nothing consumes after
P.S. Настройка для типов оставлена читателю в качестве упражнения.