ну как минимум вам мешают 2 вещи
1. это htonl/ntohl
2. это что нет стандартного типа данных 3 или 13 бит. А все остальные битовые поля компиляторо-зависимые. Проблем наживет, памяти не выиграете. Поставив поля 3 и 13 бит скорее всего будет 2 поля 8 + 16 бит, с вырезкой не пойми какой, ИМХО больше памяти пойдет чем на одно 16 битное поле.
Кстати как раз все кручение с биг и литл идет именно в заголовках. Так как в данных они лежат как послали. Компьютеры тоже Litle Endian, так что данные трогать не надо.
У вас есть некоторое непонимание происходящего, мне кажется. Если вы кладете 8 бит в 5 ячейку памяти, она так по езернету и пойдет, эти 8 бит так и останутся в 5 ячейе, никто их не переложит. Положите 16 бит, они так и будут там лежать, никто их не возьмет и не повернет.
Проблемы связаны с тем что если у вас есть 16 битное число 0xAABB в нулевой ячейке памяти, то в памяти оно ляжет в нулевую 0xBB, а в первую 0xAA, а в езернете наоборот. Соответственно когда по езернету к вам идет число 0xAABB, оно лежит в нулевой ячейке 0xAA, а в первой 0xBB, а процессор забирая его из памяти перевернет данные и вы получите 0xBBAA, потому их и надо свапануть, но это верно только если вы данные в память кладете и берете из нее словами.
Но никто вам не мешает класть данные руками по байтам, берем например число int Temp = 0xAABB. положите в 0 ячейку ((Temp >> 8)&0xFF),а в первую (Temp & 0xFF), и всех делов, сработает в любой системе хоть биг хоть литл.
И обратно
char *Data;
Temp = ((int)Data[0]<<8)|Data[1]); Опять же верно интерпретирует пришедшие по езернет данные в любой системе.