Мы опять решили написать об ненавистном всеми языке Си (КБ13 берет курс на другие модные языки).
Итак, не так давно в мыло нашей Мегакорпорации пришло письмецо от наших заказчиков. В этом письме мы обсуждаем с ними модернизацию программы РЛС одного космического корабля. Не очень ловит РЛС пока что, инопланетян с маленьким ЭПР.
Встретилась нам в письме такая структура:
typedef struct tagInstructionRadiation
{
BYTE nType : 8;
WORD wReserved1 : 8;
BYTE bSectorInhibit : 1;
BYTE bCAncelSectorInhibit : 1;
WORD wReserved2 : 3;
BYTE bRadiation : 1;
BYTE bSectorNumber : 4;
BYTE bNewSector : 1;
int nElevation : 4;
BYTE bRadiationOff : 1;
int nAzimuthBeg : 16;
int nAzimuthEnd : 16;
}InstructionRadiation;
Учитывая то, что эта структура принимается нами от заказчиков всего в 8 байт согласно протокола, КБ13 пришлось открыть стандарт языка СИ и посмотреть, что же это структура значит.
Мы не знаем таких тонкостей языка Си, т.к. пользовались ими давно в тех библиотеках, которые уже написаны и отлажены и не помним, что это такое, когда после типа данных стоит знак «:» и циферки.
Сами пользуем маски со сдвигами и всегда точно видим, как это будет выглядеть в программе, а что там компилятор накомпилирует из этих «точечек» нам не ведомо. Но мы выяснили, что для размешения компилятором переменных в то количество бит, которое стоит после каждого имени, и попадания в наши 8 байт, все типы данных структуры должны быть непременно int и/или unsigned int. Смешивать типы нельзя, как в примере выше.
Так вот вопрос для знатоков Си:
Некомпилируя рассказать нам сколько байт вернет sizeof() от такой струткуры?
Это псто написано с целью не забыть про битовые поля в языке Си. Вдруг, пригодятся кому.
sizeof() должен вернуть 8 (ну или меньше, если разрядность слова данных больше, чем 8), если мне не изменяет память, лень лазить в студию и писать код для проверки.
Ответ неверный, я таки залез в студию. Если в данном примере WORD и BYTE это int или unsigned int то будет 8. А иначе совсем не 8.
Действительно туплю! Я почему-то не обратил внимание на то, что в структуре прописано. Если все типы были бы одинаковые, то тогда 8.
накропал вот такой кусок для своего чудо-ымбеддид:
typedef struct T_Test{
Uint16 a:8;
Uint32 b:8;
}Test;
Test test;
int16 lenght;
lenght = sizeof(test);
получил lenght = 2, затем поменял Uint32 b на Uint16 b и получил как положено 1 (у меня 16-разрядное слово данных)
Что-то там можно было намутить с выравниванием, но уже не припомнить.
К нам тут заходили 2 пацана брайан и дэннис и сказале, что sizeof() возвращает размер в байтах. Но с тех времен придумали много всякого процессорного хлама и теперь он действительно возвращает в словах. И вообще общественность думаю согласится, что битовые маски все же круче.
to kamil: А что у вас за ымбедед платформо?
Да у меня ымбеддид-неымбеддид, я не знаю как правильно. Двигатели кручу TMS320F280x-ами техасовскими
Кстати, забыл упомянуть, что компилятор, который я юзаю, работу с битовыми полями в конечном счете сводит один фиг к битовым маскам. Пусть есть структура Test с битом A, тогда если написать Test.A = 1; оно скомпилируется в последовательность трех действий: берется переменная Test, делается побитовое или с (1<<N), где N — номер бита A, потом результат записывается обратно, что эквивалентно записи Test |= (1<<N). Конечно, если кроме данного бита, остальные модифицировать нельзя, по-другому не получится. Однако, в случаях когда на остальные биты в переменной (или в регистре) глубоко положить, то быстрее будет Test = (1<<N), чем Test.A = 1;
Да, кстати, структуру, описываемую в этом посте, мы, пожалуй, будем использовать как часть в определении степени гениальности при приеме новых талантов.
Кстати. Вспомнил еще один подводный камень с битовыми полями: если есть две платформы с разными endianes, то код, написанный для одной с использованием битовых полей, не будет работать на другой. Если про это забыть, то можно немало глюков наловить )