遇到了这样的情况
有如下结构体
fread(&st, sizeof(ST_1), 1, file);
例如ST_2 是按照sizoef(double)大小对齐的(也就是8Byte).
有如下结构体
struct ST_1
{
char a;
double b;
char c;
};
1. 写入文件
ST_1 st;
st.a = 'a';
st.b = 123.4;
st.c = 'b';
fwrite(&st, sizeof(ST_1), 1, file);
2. 从文件中读出来
ST_1 st;
fread(&st.a, sizeof(char), 1, file);
fread(&st.b, sizeof(double), 1, file);
fread(&st.c, sizeof(char), 1, file);
但是这样子读出来的结果是错误的. 而必须这样子读取 fread(&st, sizeof(ST_1), 1, file);
什么原因, 很明显是读取错位了. 什么原因造成错位? 这就是与结构体对齐有关.
看下面例子
struct ST_2
{
char a; // 位置在0, 大小是1
double b; // 位置在8 大小是8
char c; // 位置在16 - 1
}; // 总大小是 24 (sizeof(char) + sizeof(double) + sizeof(char) = 10 != 24
1. 首先, 一个结构体的大小是按照结构体中大小最大的那个字段对齐的.例如ST_2 是按照sizoef(double)大小对齐的(也就是8Byte).
2. 每个字段的开始位置都要在其大小的整数倍位置.
例如: ST_2.b, 大小为8Byte, 但是ST_2.a大小为1Byte, 所以ST_2.b的位置在8,
前面7个Byte就不要了.
#include "stdafx.h"
#include <iostream>
// 默认是以该结构中占最大字节数那个类型大小对齐
// 12
struct ST_0
{
char a; // 1
int b; // 4
char c; // 1
};
// 以结构中最大的那个变量的大小对齐, 这里是4字节对齐
// |--|--|--|--||--|--|--|--||--|--|--|--|
// |01|02|03|04||01|02|03|04||01|02|03|04|
// |--|--|--|--||--|--|--|--||--|--|--|--|
// |a 00 00 00||b b b b ||c 00 00 00|
// |--|--|--|--||--|--|--|--||--|--|--|--|
struct ST_0_0
{
ST_0 a;
char d;
};
// 以结构中最大的那个变量的大小对齐, 这里是4字节对齐
// |--|--|--|--||--|--|--|--||--|--|--|--||--|--|--|--|
// |01|02|03|04||01|02|03|04||01|02|03|04||01|02|03|04|
// |--|--|--|--||--|--|--|--||--|--|--|--||--|--|--|--|
// |a 00 00 00||b b b b ||c 00 00 00||d 00 00 00|
// |--|--|--|--||--|--|--|--||--|--|--|--||--|--|--|--|
// 24
struct ST_1
{
char a; // 1
double b; // 8
char c; // 1
};
// 以结构中最大的那个变量的大小对齐, 这里是8字节对齐
// |--|--|--|--|--|--|--|--||--|--|--|--|--|--|--|--||--|--|--|--|--|--|--|--|
// |01|02|03|04|05|06|07|08||01|02|03|04|05|06|07|08||01|02|03|04|05|06|07|08|
// |--|--|--|--|--|--|--|--||--|--|--|--|--|--|--|--||--|--|--|--|--|--|--|--|
// |a 00 00 00 00 00 00 00||b b b b b b b b ||c 00 00 00 00 00 00 00|
// |--|--|--|--|--|--|--|--||--|--|--|--|--|--|--|--||--|--|--|--|--|--|--|--|
// 16
struct ST_2
{
double b; // 8
char a; // 1
char c; // 1
};
// 以结构中最大的那个变量的大小对齐, 这里是8字节对齐
// |--|--|--|--|--|--|--|--||--|--|--|--|--|--|--|--|
// |01|02|03|04|05|06|07|08||01|02|03|04|05|06|07|08|
// |--|--|--|--|--|--|--|--||--|--|--|--|--|--|--|--|
// |b b b b b b b b ||a |c |00|00|00|00|00|00|
// |--|--|--|--|--|--|--|--||--|--|--|--|--|--|--|--|
// 16
struct ST_3
{
double b; // 8
char a; // 1
char c; // 1
char d; // 1
};
// 以结构中最大的那个变量的大小对齐, 这里是8字节对齐
// |--|--|--|--|--|--|--|--||--|--|--|--|--|--|--|--|
// |01|02|03|04|05|06|07|08||01|02|03|04|05|06|07|08|
// |--|--|--|--|--|--|--|--||--|--|--|--|--|--|--|--|
// |b b b b b b b b ||a |c |d |00|00|00|00|00|
// |--|--|--|--|--|--|--|--||--|--|--|--|--|--|--|--|
#pragma pack(1)
// 10
struct ST_4
{
char a; // 1
double b; // 8
char c; // 1
};
// 设置成1字节对齐
// ||--||--||--||--||--||--||--||--||--||--||
// ||01||01||01||01||01||01||01||01||01||01||
// ||--||--||--||--||--||--||--||--||--||--||
// ||a ||b ||b ||b ||b ||b ||b ||b ||b ||c ||
// ||--||--||--||--||--||--||--||--||--||--||
// 10
struct ST_5
{
double b; // 8
char a; // 1
char c; // 1
};
// 设置成1字节对齐
// ||--||--||--||--||--||--||--||--||--||--||
// ||01||01||01||01||01||01||01||01||01||01||
// ||--||--||--||--||--||--||--||--||--||--||
// ||b ||b ||b ||b ||b ||b ||b ||b ||a ||c ||
// ||--||--||--||--||--||--||--||--||--||--||
#pragma pack()
int _tmain(int argc, _TCHAR* argv[])
{
std::cout << "ST_0 :" << sizeof(ST_0) << std::endl;
std::cout << "ST_0_0 :" << sizeof(ST_0_0) << std::endl;
std::cout << "ST_1 :" << sizeof(ST_1) << std::endl;
std::cout << "ST_2 :" << sizeof(ST_2) << std::endl;
std::cout << "ST_3 :" << sizeof(ST_3) << std::endl;
std::cout << "ST_4 :" << sizeof(ST_4) << std::endl;
std::cout << "ST_5 :" << sizeof(ST_5) << std::endl;
return 0;
}