问我该如何编写代码来符合这些旧的二进制数据文件格式?
答这很困难,因为存在字大小和字节顺序的差异、浮点格式以及结构填充。为了获得您所需要的对这些细节的控制,您可能需要一次读取和写入一个字节,在移动和重新排列的过程中进行处理。(这并不总是听起来那么糟糕,并且可以使您的代码具有可移植性并提供完全的控制。)
例如,要从流fp中读取一个由字符、一个 32 位整数和一个 16 位整数组成的数据结构,并将其读入 C 结构
struct mystruct { char c; long int i32; int i16; } s;您可以使用类似这样的代码
s.c = getc(fp); s.i32 = (long)getc(fp) << 24; s.i32 |= (long)getc(fp) << 16; s.i32 |= (unsigned)(getc(fp) << 8); s.i32 |= getc(fp); s.i16 = getc(fp) << 8; s.i16 |= getc(fp);此代码假定getc读取 8 位字符,并且数据以最高有效字节在前(“大端”)的方式存储。转换为(long)可确保 16 位和 24 位移位操作在long值上进行(请参阅问题 3.14),转换为(unsigned)可防止符号扩展。(总的来说,在编写此类代码时使用所有unsigned类型更安全,但请参阅问题 3.19。)
相应地编写该结构可能看起来像
putc(s.c, fp); putc((unsigned)((s.i32 >> 24) & 0xff), fp); putc((unsigned)((s.i32 >> 16) & 0xff), fp); putc((unsigned)((s.i32 >> 8) & 0xff), fp); putc((unsigned)(s.i32 & 0xff), fp); putc((s.i16 >> 8) & 0xff, fp); putc(s.i16 & 0xff, fp);
另请参阅问题 2.12、12.38、16.7 和 20.5。