当前位置:  开发笔记 > 编程语言 > 正文

C / C ++中的内存对齐

如何解决《C/C++中的内存对齐》经验,为你挑选了1个好方法。

我正在阅读《游戏编码完整版》第4版。有一个关于内存对齐的主题。在下面的代码中,作者说,第一个结构确实很慢,因为它既没有位对齐也没有字节对齐。第二个不是位对齐而是字节对齐。最后一个很快,因为两者都有。他说,没有编译指示,编译器将对齐内存本身,这会浪费内存。我无法真正获得计算结果。

这是文本的一部分:

如果让编译器通过添加未使用的字节来优化SlowStruct,则每个结构将是24个字节而不是14个字节。在第一个char变量之后填充七个额外的字节,并在末尾添加其余字节。这样可以确保整个结构始终以8字节为边界开始。这大约是浪费空间的40%,这都是由于成员变量的粗心排序所致。

这是粗体字的结论行:-

不要让编译器浪费宝贵的内存空间。让您的一些 脑细胞发挥作用,并对齐您自己的成员变量。

请让我看一下计算并更清楚地解释填充概念。

码:-

#pragma pack(push, 1)
struct ReallySlowStruct
{
    char c : 6;
    __int64 d : 64;
    int b : 32;
    char a : 8;
};

struct SlowStruct
{
    char c;
    __int64 d;
    int b;
    char a;
};

struct FastStruct
{
   __int64 d;
   __int b;
   char a;
   char c;
   char unused[2];
};
#pragma pack(pop)

jwsc.. 6

本书中给出的示例高度依赖于所使用的编译器和计算机体系结构。如果在自己的程序中测试它们,则可能会得到与作者完全不同的结果。我将假定使用64位体系结构,因为作者也会这样做,因为我在描述中已经读过。让我们一一查看示例:

如果所使用的编译器支持非字节对齐的结构成员,则ReallySlowStruct,“ d”的开头将在结构的第一个字节的第七位。听起来非常节省内存。问题是,C不允许位处理。因此,要将newValue保存到“ d”成员,编译器必须执行很多移位操作:将“ newValue”的前两位保存在byte0中,向右移6位。然后将“ newValue”向左移两位,并从字节1开始保存。字节1是未对齐的存储器位置,这意味着大容量存储器传输指令将不起作用,编译器必须一次保存每个字节。

SlowStruct 变得更好。编译器可以摆脱所有的麻烦。但是,写入“ d”仍然需要一次写入每个字节,因为它与本机“ int”的大小不匹配。在64位系统上,本机大小为8。因此,每个不可被8整除的内存地址一次只能访问一个字节。更糟糕的是,如果我关闭打包,则会浪费大量的内存空间:每个成员后面跟一个int都将填充足够的字节,以使整数从8的可除内存位置开始。在这种情况下:char a和c都将占用8个字节。

FastStruct, 它与目标计算机上int的大小对齐。“ b”占用了8个字节。因为所有字符都捆绑在一个位置,所以编译器不会填充它们,也不会浪费空间。每个字符只有1个字节,因此我们不需要填充它们。完整的结构总计为16个字节。除以8,因此无需填充。



1> jwsc..:

本书中给出的示例高度依赖于所使用的编译器和计算机体系结构。如果在自己的程序中测试它们,则可能会得到与作者完全不同的结果。我将假定使用64位体系结构,因为作者也会这样做,因为我在描述中已经读过。让我们一一查看示例:

如果所使用的编译器支持非字节对齐的结构成员,则ReallySlowStruct,“ d”的开头将在结构的第一个字节的第七位。听起来非常节省内存。问题是,C不允许位处理。因此,要将newValue保存到“ d”成员,编译器必须执行很多移位操作:将“ newValue”的前两位保存在byte0中,向右移6位。然后将“ newValue”向左移两位,并从字节1开始保存。字节1是未对齐的存储器位置,这意味着大容量存储器传输指令将不起作用,编译器必须一次保存每个字节。

SlowStruct 变得更好。编译器可以摆脱所有的麻烦。但是,写入“ d”仍然需要一次写入每个字节,因为它与本机“ int”的大小不匹配。在64位系统上,本机大小为8。因此,每个不可被8整除的内存地址一次只能访问一个字节。更糟糕的是,如果我关闭打包,则会浪费大量的内存空间:每个成员后面跟一个int都将填充足够的字节,以使整数从8的可除内存位置开始。在这种情况下:char a和c都将占用8个字节。

FastStruct, 它与目标计算机上int的大小对齐。“ b”占用了8个字节。因为所有字符都捆绑在一个位置,所以编译器不会填充它们,也不会浪费空间。每个字符只有1个字节,因此我们不需要填充它们。完整的结构总计为16个字节。除以8,因此无需填充。

推荐阅读
手机用户2402851335
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有