一个布尔类型为什么占用的内存与整型相同?C++

7

当我在dev cpp中运行这个程序时,任务管理器显示它大约为79 MB。Codeforces使用gnu c++ 4.7编译器则显示它是79112千字节。

#include<stdio.h>
const int N=10010,K=1010;
struct TPos
{
    int charge;
    bool ex;
    TPos()
    {
        charge=1<<30;
        ex=false;    
    }  
};
TPos d[N][K];

int main()
{
    while(1);
    return 0;
}

但是当ex参数被注释时:

#include<stdio.h>
const int N=10010,K=1010;
struct TPos
{
    int charge;
    //bool ex;
    TPos()
    {
        charge=1<<30;
        //ex=false;    
    }  
};
TPos d[N][K];

int main()
{
    //while(1);
    return 0;
}

这个文件只有39536 KB。我以为布尔类型只需要一个字节,为什么会使文件大小翻倍呢?


3
填充。 - BoBTFish
1
你可以尝试使用 attribute((packed)) 来查看它的效果(但对于性能来说通常不是一个好的做法)。 - Leeor
1
如果您不需要所有int位进行"charge"操作,甚至可以将内存需求降低到sizeof(int)。请参考下面的答案。(也许在charge中多或少2的幂次方并没有太大的区别。) - Tobias
6个回答

10

如果不对结构体进行打包,它将始终占用可被字大小整除的内存(由于内存对齐)。您可以使用gcc中的__attribute__(packed)来打包结构体。例如,请参见此处。打包结构体可能会减少所需内存,但几乎肯定会减慢执行速度。


2
没错,这是可能的,但这可能不是一个好的实践,因为它可能会破坏对齐,并增加虚假缓存行冲突的机会。另请参见- http://digitalvampire.org/blog/index.php/2006/07/31/why-you-shouldnt-use-__attribute__packed/ - Leeor

6

布尔型是一个字节,但你在这里看到的是结构体对齐。

因为你的结构体包含一个整数,所以编译器自动将结构体按照整数大小对齐,以确保它在数组中得到正确对齐。否则,你的数组的第二个元素可能会在错误的地址上存储整数 - 这可能会导致性能下降,并且在某些架构上甚至会导致崩溃。

你可以使用编译器特定的pragma和属性来明确关闭结构体对齐,但你不想这样做。如果内存是一个关注点,考虑使用数组的结构体而不是结构体的数组。


3
由于内存对齐,这个boolstruct中与int对齐。意味着有一些额外未使用的字节。

这意味着sizeof( your_struct )会给出2 * sizeof(int)

您可以进行一些实验 - 检查结构中更多的boolsizeof(一个接一个),重新排序元素后再次检查大小等。这些是了解发生的情况的有用实验。此外,研究结构填充和内存对齐对您非常有用。


1
你可以使用大小规格说明符来减小对象的大小(请参见以下代码中的)。如果你不是真正需要完整的int大小来处理charge,那么这可能会像TPosB一样。
#include <iostream>

#include<stdio.h>
struct TPosB
{
    int charge : sizeof(int)-1;
    bool ex : 1;
    TPosB()
    {
        charge=1 << sizeof(int)-2;
        ex=false;
    }
};
TPosB b;

struct TPos
{
    int charge;
    bool ex;
    TPos()
    {
        charge=1<<30;
        ex=false;    
    }  
};
TPos a;

int main()
{
    std::cout << "sizeof(int)" << sizeof(int);
    std::cout << "\nsizeof(a)=" << sizeof(a);
    std::cout << "\nsizeof(b)=" << sizeof(b);

    return 0;
}

1

这与结构对齐有关。在某些平台上,如果内存是4字节的倍数,则更容易寻址。编译器可能会填充您的结构以使其更易于使用。

如果我没错的话,您可以添加另一个bool变量,并且不会看到额外使用的空间。

检查编译器选项以了解如何禁用它,但请注意性能可能会受到影响。


1

确实,bool通常使用一个字节(但不一定)。

然而,C和C++也允许在结构体中添加填充,即空白空间,以便进行对齐。这有点复杂,但基本上当变量按特定边界对齐时,内存访问就会变得更快。

在这种情况下,添加额外的bool可能已经将结构体大小从4个字节(仅针对int)增加到8个字节,以便在数组中很好地对齐结构体。当然,这都取决于你的编译器,但你可以使用sizeof(TPos)来检查。

大多数编译器都有扩展功能,请求特定的结构体被填充,即使这样会使它们使用起来更慢--你可能需要研究一下这个。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接