简体   繁体   English

如何使以下 C 结构更高效 memory?

[英]How do I make the following C structure more memory efficient?

I am trying to solve a rather challenging programming task.我正在尝试解决一个相当具有挑战性的编程任务。 We are given the following 64-bit structure, which allows us to store a point in time accurate to the minute:我们得到以下 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

This structure has the size of 12 Bytes (I checked this and the struct really does use so much space).这个结构的大小为 12 字节(我检查了这个,结构确实使用了这么多空间)。 The task is to reduce the size to 8 Bytes and we are not allowed to use unions.任务是将大小减少到 8 字节,我们不允许使用联合。 We are supposed to use a lot of these structures, hence why we want to reduce the memory size.我们应该使用很多这样的结构,因此我们要减小 memory 的大小。

The only thing I can think of is to change the unsigned int to unsigned short , but how can we get rid of the other two Bytes?我唯一能想到的就是将unsigned int更改为unsigned short ,但是我们怎样才能摆脱其他两个字节呢?

Kind regards亲切的问候

The main problem here is that char have no alignment requirement, but int has a requirement of 4 byte alignment (on a 32 bit system).这里的主要问题是char没有 alignment 要求,但int要求 4 字节 alignment (在 32 位系统上)。 Meaning it must start at an address divisible by 4. Structs are guaranteed to start at an aligned address, so what you get is likely this:这意味着它必须从可被 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!

The first two padding bytes are there to ensure that the int is aligned, the last two are there to ensure that the next struct in an array of structs start at an aligned address.前两个填充字节用于确保int对齐,后两个填充字节用于确保结构数组中的下一个结构从对齐的地址开始。

The fix is simple, just move year to the top of the struct:修复很简单,只需将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

And now the struct should be 8 bytes large with zero padding.现在结构应该是 8 字节大,填充为零。

Your current struct, since sizeof(Time) == 12 and sizeof(unsigned int) == 4 is layed out like this:您当前的结构,因为sizeof(Time) == 12sizeof(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; 

You can reduce the size to 8 by moving year first.您可以通过先移动year将大小减小到 8。 No padding needed here:这里不需要填充:

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; 

The compiler aligns the data based on the alignment of the next field of a structure, in your case you have two char fields that have alignment of 1 (any address is valid to hold a char) but the int type (32bit) has an alignment requirement of 4bytes, so, as the offset when the second char element is 2, it needs to add two alignment spaces to make it properly aligned (to an address multiple of 4) and it also makes the whole struct to be 4 aligned , so when the struct end arrives, there's an alignment of 4 for the next structure of this type (to properly conserve the alignment of the full structure in arrays) and so, it needs to add two more bytes to the end of the structure. The compiler aligns the data based on the alignment of the next field of a structure, in your case you have two char fields that have alignment of 1 (any address is valid to hold a char) but the int type (32bit) has an alignment要求 4bytes,所以,作为第二个char元素为 2 时的偏移量,需要添加两个 alignment 空格以使其正确对齐(到 4 的地址倍数),并且它也使整个struct为 4 对齐,所以当结构结束时,对于这种类型的下一个结构,有一个为 4 的 alignment(为了适当地保存数组中完整结构的 alignment),因此,它需要在结构的末尾再添加两个字节。 This makes the four bytes you observe in your code.这使得您在代码中观察到的四个字节。

To optimize, just put the large fields first on the structure, and fill it later at the end with the smaller data (that has less alignment requirements) This way, the structure aligns better with the bigger fields and the fields tend to fill the holes made by alignment.为了优化,只需将大字段首先放在结构上,然后在最后用较小的数据填充它(对 alignment 的要求较少)这样,结构与较大的字段更好地对齐,并且字段倾向于填充孔由 alignment 制造。 if you had used, instead:如果您使用过,请改为:

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)
};

you will get a 32 byte structure (a worst case, as it resulted in 25 packed bytes, so the next multiple of 8 is 32)你会得到一个 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) == %zu\n", sizeof (struct my_struct));
}

which produces:产生:

$ a.out
sizeof (struct my_struct) == 32
$ _

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM