5
  struct {              /* Fileheader */
    uchar file_version[4];
    uchar options[2];
    uchar header_length[2];
    uchar state_info_length[2];
    uchar base_info_length[2];
    uchar base_pos[2];
    uchar key_parts[2];         /* Key parts */
    uchar unique_key_parts[2];      /* Key parts + unique parts */
    uchar keys;             /* number of keys in file */
    uchar uniques;          /* number of UNIQUE definitions */
    uchar language;         /* Language for indexes */
    uchar max_block_size_index;     /* max keyblock size */
    uchar fulltext_keys;
    uchar not_used;                     /* To align to 8 */
  } header;

以上摘自MySQL源码,

为什么要对齐8

4

3 回答 3

6

这是一种优化,允许 CPU 更有效地访问内存中的结构。

http://en.wikipedia.org/wiki/Data_structure_alignment

于 2011-10-24T02:54:56.403 回答
3

原因 1:地址计算更快更小。

在 x86 以及其他一些架构上,如果元素大小是“不错的整数”,则访问数组元素的效率更高。对于“nice, round number”的定义,学习x86汇编。但是您可以看到以下代码在汇编中访问具有不同大小元素的数组的效果:

struct s { char c[N]; };
int func(struct s *p, int i) { return p[i].c[0]; }

当 N 为 23 时(上述结构的大小没有填充):

leaq    (%rsi,%rsi,2), %rax
salq    $3, %rax
subq    %rsi, %rax
movsbl  (%rax,%rdi),%eax

当 N 为 24 时(上述结构的大小与填充):

leaq    (%rsi,%rsi,2), %rax
movsbl  (%rdi,%rax,8),%eax

当 N 为 32 时(上述结构的大小加上额外的填充):

salq    $5, %rsi
movsbl  (%rsi,%rdi),%eax

请注意,用于访问具有 23 字节元素的数组中的元素的代码是多么复杂。

原因 2:对于磁盘结构,它允许使用对齐的加载和存储访问文件中的其他元素。

看起来结构出现在磁盘上。使用填充,32 位字可以直接出现在结构之后并对齐。这使得访问速度更快——编译器会自动为内存中的结构执行此操作,但您需要为磁盘上的结构手动执行此操作。如果您尝试访问未对齐的数据,某些架构甚至会崩溃。

unsigned char *data = ...;
header *h = (header *) data;
do_something_with(h);
uint32_t x = *(uint32_t *) (data + sizeof(header));

sizeof(header)如果不是 4 的倍数,上面的代码将导致 SPARC 崩溃,并且在 x86 上它会更慢,除非sizeof(header)不是 4 的倍数。

于 2011-10-24T03:17:20.730 回答
1

如果标头结构在数组中,则数组的所有元素将以相同的方式对齐。否则,就不会这样了。您可以查看下面的代码/输出来验证这一点。

如果Dani在他们的评论中是正确的,用户打算将类似的东西file_version转换为 a uint32_t,那么这种对齐方式将非常重要。

一些代码

#include <stdio.h>

struct padded {
    unsigned char file_version[4];
    unsigned char options[2];
    unsigned char header_length[2];
    unsigned char state_info_length[2];
    unsigned char base_info_length[2];
    unsigned char base_pos[2];
    unsigned char key_parts[2];
    unsigned char unique_key_parts[2];
    unsigned char keys;
    unsigned char uniques;
    unsigned char language;
    unsigned char max_block_size_index;
    unsigned char fulltext_keys;
    unsigned char not_used;
};

struct unpadded {
    unsigned char file_version[4];
    unsigned char options[2];
    unsigned char header_length[2];
    unsigned char state_info_length[2];
    unsigned char base_info_length[2];
    unsigned char base_pos[2];
    unsigned char key_parts[2];
    unsigned char unique_key_parts[2];
    unsigned char keys;
    unsigned char uniques;
    unsigned char language;
    unsigned char max_block_size_index;
    unsigned char fulltext_keys;
};

int main() {
    printf("size padded:      %lu\n", sizeof(struct padded));
    printf("size unpadded:    %lu\n", sizeof(struct unpadded));

    printf("size padded[2]:   %lu\n", sizeof(struct padded[2]));
    printf("size unpadded[2]: %lu\n", sizeof(struct unpadded[2]));
}

输出

size padded:      24
size unpadded:    23
size padded[2]:   48
size unpadded[2]: 46
于 2011-10-24T03:11:58.840 回答