我正试图解决一项极具挑战性的编程任务。我们得到了以下64位结构,它允许我们存储精确到分钟的时间点:
typedef struct
{
unsigned char day; //1 Byte
unsigned char month; //1 Byte
unsigned int year; //4 Bytes
unsigned char hours; //1 Byte
unsigned char minutes; //1 Byte
} Time; //4 Bytes are probably used for padding
这个结构的大小是12字节(我检查过了,这个结构确实占用了太多空间(。任务是将大小减少到8字节,我们不允许使用联合。我们应该使用很多这样的结构,因此我们想要减小内存大小。
我唯一能想到的就是把unsigned int
改成unsigned short
,但我们怎么能去掉另外两个字节呢?
问候
这里的主要问题是char
没有对齐要求,但int
有4字节对齐的要求(在32位系统上(。这意味着它必须从一个可以被4整除的地址开始。结构保证从一个对齐的地址开始,所以你得到的可能是:
unsigned char day; //1 Byte
unsigned char month; //1 Byte
// 2 byte padding!
unsigned int year; //4 Bytes
unsigned char hours; //1 Byte
unsigned char minutes; //1 Byte
// 2 byte padding!
前两个填充字节用于确保int
对齐,后两个用于确保结构数组中的下一个结构从对齐的地址开始。
修复很简单,只需将year
移动到结构的顶部:
unsigned int year; //4 Bytes
unsigned char day; //1 Byte
unsigned char month; //1 Byte
unsigned char hours; //1 Byte
unsigned char minutes; //1 Byte
现在这个结构应该是8字节大,并且没有填充。
您当前的结构,因为sizeof(Time) == 12
和sizeof(unsigned int) == 4
的布局如下:
typedef struct
{
unsigned char day; //1 Byte
unsigned char month; //1 Byte
// 2 bytes padding to align the `unsigned int`
unsigned int year; //4 Bytes
unsigned char hours; //1 Byte
unsigned char minutes; //1 Byte
// 2 bytes padding
} Time;
您可以通过先移动year
将大小减小到8。此处无需填充:
typedef struct
{
unsigned int year; //4 Bytes
unsigned char day; //1 Byte
unsigned char month; //1 Byte
unsigned char hours; //1 Byte
unsigned char minutes; //1 Byte
} Time;
编译器根据结构的下一个字段的对齐方式来对齐数据,在您的情况下,有两个对齐方式为1的char
字段(任何地址都可以有效地保存字符(,但int
类型(32位(的对齐要求为4字节,因此,由于第二个char
元素为2时的偏移量,它需要添加两个对齐空间以使其正确对齐(到4的地址倍数(,它还使整个struct
对齐,因此当结构端到达时,该类型的下一个结构的对齐为4(以适当地保留数组中整个结构的对齐(,因此,它需要在结构端再添加两个字节。这就形成了您在代码中观察到的四个字节。
要进行优化,只需将大字段放在结构上的第一位,然后在最后用较小的数据填充(对齐要求较少(通过这种方式,结构与较大的场更好地对齐,并且场倾向于填充通过对齐形成的孔。如果您使用过,请改为:
struct my_struct {
double time_as_double; // normally 8 byte alignment
char *timezone; // 8 byte alignment in 64bit architectures.
int year; // 4 byte alignment
unsigned char month, // one byte alignment
mday, // one byte alignment
hour, // one byte alignment
min, // one byte alignment
sec; // one byte alignment
// seven more bytes of alignment to comply with 8 byte alignment for the
// full structure (to allow it to form arrays)
};
你会得到一个32字节的结构(最坏的情况是,它产生了25个压缩字节,所以8的下一个倍数是32(
#include <stdio.h>
struct my_struct {
double time_as_double; // normally 8 byte alignment
char *timezone; // 8 byte alignment in 64bit architectures.
int year; // 4 byte alignment
unsigned char month, // one byte alignment
mday, // one byte alignment
hour, // one byte alignment
min, // one byte alignment
sec; // one byte alignment
// seven more bytes of alignment to comply with 8 byte alignment for the
// full structure (to allow it to form arrays)
};
int main()
{
printf("sizeof (struct my_struct) == %zun", sizeof (struct my_struct));
}
其产生:
$ a.out
sizeof (struct my_struct) == 32
$ _