sizeof和alignof有什么区别?
#include <iostream>
#define SIZEOF_ALIGNOF(T) std::cout<< sizeof(T) << '/' << alignof(T) << std::endl
int main(int, char**)
{
SIZEOF_ALIGNOF(unsigned char);
SIZEOF_ALIGNOF(char);
SIZEOF_ALIGNOF(unsigned short int);
SIZEOF_ALIGNOF(short int);
SIZEOF_ALIGNOF(unsigned int);
SIZEOF_ALIGNOF(int);
SIZEOF_ALIGNOF(float);
SIZEOF_ALIGNOF(unsigned long int);
SIZEOF_ALIGNOF(long int);
SIZEOF_ALIGNOF(unsigned long long int);
SIZEOF_ALIGNOF(long long int);
SIZEOF_ALIGNOF(double);
}将输出
1/1 1/1 2/2 2/2 4/4 4/4 4/4 4/4 8/8 8/8 8/8
我想我不明白什么是对齐...?
发布于 2012-07-09 05:48:52
嗯,“内存”基本上是一个巨大的字节数组。然而,大多数更大的东西,如整数,需要超过1个字节来存储它们--例如,一个32位的值将使用4个连续的字节的内存。
现在,计算机中的内存模块通常不是“字节”的;它们也是由几个字节“并行”组织的,就像4个字节的块。
对于CPU,在读取像整数这样的东西时,不“跨越”这样的块边界要容易得多,效率更高,性能更好:
memory byte 0 1 2 3 4 5 6 7 8 9 10 11
integer goooood
baaaaaaaaad这就是“对齐”所说的:对齐4意味着这种类型的数据应该(或必须取决于CPU)从4的倍数的地址开始存储。
您观察到sizeof==alignof是不正确的;请尝试结构。结构也将对齐(因为它们的单个成员需要在正确的地址上结束),但它们的大小将大得多。
发布于 2016-12-01 19:14:14
对于所提供的答案,似乎有一些关于对齐实际是什么的困惑。混淆可能是因为有两种对齐方式。
1.成员对齐
这是一种定性度量,它用字节数来表示实例在结构/类类型中的特定成员排序有多大。通常,如果成员在结构中按字节大小降序排序(即最大的成员在前面,最小的成员在最后),编译器可以压缩结构/类实例。考虑一下:
struct A
{
char c; float f; short s;
};
struct B
{
float f; short s; char c;
};这两个结构包含完全相同的信息。就本例而言,float类型占用4个字节,short类型占用2个字节,而character占用1个字节。但是,第一个结构A具有随机顺序的成员,而第二个结构B根据成员的字节大小对成员进行排序(这在某些体系结构上可能不同,在本例中我假设x86英特尔CPU体系结构具有4字节对齐)。现在考虑结构的大小:
printf("size of A: %d", sizeof (A)); // size of A: 12;
printf("size of B: %d", sizeof (B)); // size of B: 8;如果预期大小为7字节,则假定成员是使用1字节对齐方式打包到结构中的。虽然有些编译器允许这样做,但一般来说,由于历史原因(大多数CPU使用DWORD (双字)或QWORD (四字)通用寄存器),大多数编译器使用4字节甚至8字节对齐。
有两个填充机制在工作,以实现包装。
请注意,Visual C++ / GCC允许1字节、2字节和2字节的更高倍数的不同对齐。要知道,这与编译器为体系结构生成最佳代码的能力背道而驰。实际上,在下面的示例中,对于每个读取操作,将使用单字节指令将每个字节读取为单个字节。在实践中,硬件仍将取出包含读取到高速缓存中的每个字节的整个存储器线,并执行指令4次,即使这4个字节位于相同的DWORD中并且可以在1条指令中加载到CPU寄存器中。
#pragma pack(push,1)
struct Bad
{
char a,b,c,d;
};
#pragma pack(pop)2.分配对齐
这与上一节中解释的第二个填充机制密切相关,但是,分配对齐可以在malloc() / memalloc()分配函数的变体中指定,例如std::aligned_alloc()。因此,可以在结构/对象类型的字节对齐建议的不同(通常是2的较高倍数)对齐边界上分配对象。
size_t blockAlignment = 4*1024; // 4K page block alignment
void* block = std::aligned_alloc(blockAlignment, sizeof(T) * count);代码将把类型T的count实例块放在以4096的倍数结尾的地址上。
使用这种分配对齐的原因也是纯粹的架构。例如,从页面对齐的地址读取和写入块的速度更快,因为地址范围非常适合缓存层。当跨越页面边界时,拆分到不同“页面”上的范围将回收缓存。不同的介质(总线架构)具有不同的访问模式,并且可以从不同的对齐中受益。通常,4、16、32和64K页面大小的对齐并不少见。
请注意,语言版本和平台通常会提供这种对齐分配函数的特定变体。例如,Unix/Linux兼容的posix_memalign()函数通过ptr参数返回内存,并在失败的情况下返回非零的错误值。
空对齐整数对齐( // POSIX(Linux/UX)
发布于 2012-07-09 05:45:31
这两个运算符做的是完全不同的事情。sizeof给出了一个类型的大小(它需要多少内存),而alignof给出了一个类型必须与多少字节对齐。碰巧您测试的原语具有与其大小相同的对齐要求(如果您仔细考虑一下,这是有意义的)。
想一想,如果你有一个结构,会发生什么:
struct Foo {
int a;
float b;
char c;
};alignof(Foo)将返回4。
https://stackoverflow.com/questions/11386946
复制相似问题