Корректно паковать типы данных в байты самому, так гарантированно не будет проблем с переносимостью между компиляторами, с размерами типов данных и порядком байт.unsigned char buff[7];
buff[0] = byte_var & 0xff;
buff[1] = word_var & 0xff;
buff[2] = (word_var << 8) & 0xff;
buff[3] = dword_var & 0xff;
buff[4] = (dword_var << 8) & 0xff;
buff[5] = (dword_var << 16) & 0xff;
buff[6] = (dword_var << 24) & 0xff;
byte_var = buff[0];
word_var = buff[1] | ((word)buff[2] << 8));
dword_var = buff[3] | ((dword)buff[4] << 8)) | ((dword)buff[5] << 16)) | ((dword)buff[6] << 24));
word и dword - ваши типы для word и dword соответственно. Обычно нет смысла использовать для обоих что-либо отличное от (unsigned)int.
Кстати в такой структуре:
typedef struct Test1_stru {
unsigned char byte;
unsigned short int word;
unsigned int dword;
} __attribute__((__packed__)) Test1 ;
поля лучше хранить в обратном порядке (самые широкие в начале), а все эти __attribute__((__packed__)) - ересь