Трюки программирования
компилятора при включении заголовочных файлов, но, поверьте, он существует.
Отладка программы, содержащую подобную ошибку, оказывается проверкой на устойчивость психики. Потому что выглядит это примерно так: следим за объектом, за его полями, все выглядит просто замечательно и вдруг, после того как управление передается какой то функции, все, что содержится в объекте, принимает «бредовые» формы, какие то неизвестно откуда взявшиеся цифры...
На самом деле #pragma pack не является панацеей. Мало того, использование этой директивы практически всегда неправомерно. Можно даже сказать, что эта директива в принципе редко когда нужна (во всяком случае, при прикладном программировании).
Правильным же подходом является сначала записать все поля структуры в нужном порядке в некоторый буфер и скидывать в файл уже содержимое буфера. Это очень просто и очень эффективно, потому что все операции чтения/записи можно собрать в подпрограммы и менять их при необходимости таким образом, чтобы обеспечить нормальную работу с внешними файлами. Проиллюстрируем этот подход:
template<class T>
inline size_t get_size(const T& obj)
{
return sizeof(obj);
}
Эта функция возвращает размер, необходимый для записи объекта. Зачем она понадобилась? Во первых, возможен вариант, что sizeof возвращает размер не в байтах, а в каких то собственных единицах. Во вторых, и это значительно более необходимо, объекты, для которых вычисляется размер, могут быть не настолько простыми, как int. Например:
template<>
inline size_t get_size<std::string>(const std::string& s)
{
return s.length() + 1;
}
Надеемся, понятно, почему выше нельзя было использовать sizeof.