首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >对齐到8的原因是什么?

对齐到8的原因是什么?
EN

Stack Overflow用户
提问于 2011-10-24 10:51:49
回答 3查看 1.5K关注 0票数 5
代码语言:javascript
复制
  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

EN

回答 3

Stack Overflow用户

发布于 2011-10-24 10:54:56

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

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

票数 6
EN

Stack Overflow用户

发布于 2011-10-24 11:17:21

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

在x86和其他一些架构上,如果元素大小是一个“漂亮的四舍五入数”,那么访问数组的元素会更有效率。对于“好的,四舍五入的数字”的定义,学习x86汇编。但是对于以下代码,您可以看到在程序集中访问具有不同大小元素的数组的效果:

代码语言:javascript
复制
struct s { char c[N]; };
int func(struct s *p, int i) { return p[i].c[0]; }

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

代码语言:javascript
复制
leaq    (%rsi,%rsi,2), %rax
salq    $3, %rax
subq    %rsi, %rax
movsbl  (%rax,%rdi),%eax

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

代码语言:javascript
复制
leaq    (%rsi,%rsi,2), %rax
movsbl  (%rdi,%rax,8),%eax

当N为32时(具有附加填充的上述结构的大小):

代码语言:javascript
复制
salq    $5, %rsi
movsbl  (%rsi,%rdi),%eax

请注意,访问包含23字节元素的数组中的元素的代码有多复杂。

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

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

代码语言:javascript
复制
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的倍数,否则速度会更慢。

票数 3
EN

Stack Overflow用户

发布于 2011-10-24 11:11:59

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

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

一些代码

代码语言:javascript
复制
#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]));
}

输出

代码语言:javascript
复制
size padded:      24
size unpadded:    23
size padded[2]:   48
size unpadded[2]: 46
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/7870903

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档