C++ 什么';sizeof和alignof的区别是什么?

C++ 什么';sizeof和alignof的区别是什么?,c++,c++11,sizeof,alignof,C++,C++11,Sizeof,Alignof,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之间有什么区别

#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);
}
#包括
#define SIZEOF_ALIGNOF(T)std::cout以字节为单位提供实际类型或类型实例的大小


提供给定类型的任何实例所需的以字节为单位的对齐方式。

这两个运算符的作用完全不同
sizeof
给出类型的大小(需要多少内存),而
alignof
给出类型必须对齐的字节数。恰好您测试的原语有一个与其大小相同的对齐要求(如果您仔细考虑的话,这是有道理的)

考虑一下,如果使用结构,会发生什么:

struct Foo {
     int a;
     float b;
     char c;
};
alignof(Foo)
将返回4。

嗯,“内存”基本上是一个庞大的字节数组。然而,大多数较大的东西,如整数,需要超过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不正确;试试结构。结构也将对齐(因为它们的单个成员需要在正确的地址上结束),但它们的大小将大得多。

对于基本类型,alignof值与sizeof值相同

区别在于所使用的定义数据类型,如使用struct;对于一个例子来说

typedef struct { int a; double b; } S;
//cout<<alignof(s);                              outputp: 8;
//cout<<sizeof(S);                               output: 12;
typedef结构{inta;双b;}S;
//cout旧问题(虽然没有标记为已回答),但认为除了Christian Stieber的答案外,这个例子使区别更加明确。此外,Meluha的回答包含一个错误,因为sizeof(s)输出是16而不是12

// c has to occupy 8 bytes so that d (whose size is 8) starts on a 8 bytes boundary
//            | 8 bytes |  | 8 bytes  |    | 8 bytes |
struct Bad  {   char c;      double d;       int i;     }; 
cout << alignof(Bad) << " " << sizeof(Bad) << endl;   // 8 24

//             | 8 bytes |   |   8 bytes    |    
struct Good {   double d;     int i; char c;          };
cout << alignof(Good) << " " << sizeof(Good) << endl; // 8 16
//c必须占用8个字节,以便d(大小为8)从8个字节的边界开始
//| 8字节| | 8字节| | 8字节|
结构错误{char c;double d;int i;};

cout对于提供的答案,似乎有一些关于对齐实际是什么的混淆。这种混淆可能是因为有两种对齐方式

1。成员一致性

这是一个定性的度量,说明对于结构/类类型中特定的成员顺序,实例的字节数有多大。通常,如果结构中的成员按字节大小降序排列(即最大的成员排在第一,最小的成员排在最后),编译器可以压缩结构/类实例。考虑:

struct A
{
  char c; float f; short s;
};

struct B
{
  float f; short s; char c;
};
两个结构包含完全相同的信息。为了这个例子;浮点类型需要4个字节,短类型需要2个字节,字符需要1个字节。但是,第一个结构A的成员顺序是随机的,而第二个结构B的成员顺序是根据字节大小(在某些体系结构上可能有所不同,在本例中,我假设采用4字节对齐的x86 intel CPU体系结构)。现在考虑结构的大小:

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字节对齐

有两个填充机制在工作,以实现包装

  • 首先,如果生成的字节大小小于或等于字节对齐方式,则每个字节大小小于字节对齐方式的成员将与下一个成员“合并”。在结构B中,成员s和c可以这样合并;它们的组合大小是s为2字节,c为1字节==3字节
    sizeof
    alignof
    之间有什么区别

    两者都是运营商。两者都返回一种类型的
    size\u t

    sizeof
    是对象的大小(以“字节”为单位),即编码对象所需的内存空间

    alignof
    是对象的“字节”地址对齐要求。值为1表示没有对齐限制。2表示地址应为偶数地址。4表示地址应为四元地址。等等

    当尝试不符合对齐要求的对象引用时,结果是未定义的行为。
    示例:
    . 访问可能会工作,但速度较慢。
    . 访问尝试可能会终止程序

    // Assume alignof(int) --> 2
    char a[4];   // It is not known that `a` begins on an odd or even address
    int *p = a;  // conversion may fail
    int d = *p;  // *p is UB.
    
    OP代码的扩展和输出示例

      SIZEOF_ALIGNOF(double);
      SIZEOF_ALIGNOF(complex double);
      SIZEOF_ALIGNOF(div_t);
      SIZEOF_ALIGNOF(max_align_t);
    
    8/8
    16/8
    8/4
    32/16
    

    请使用结构而不是本机类型重试此操作。
    返回给定类型的任何实例所需的字节对齐方式(2的整数幂)
    sizeof
    当然只是给出了大小,以字节为单位。也许值得一提——额外的一点——尽管x86在大多数情况下都会执行未对齐的读写操作(缓慢但正确),但有些体系结构要求所有操作都要对齐,甚至在x86中也有一些特殊情况必须对齐(我认为是SIMD指令)@ USE1494506-如果这个或任何其他答案正确地回答你的问题,考虑标记它是正确的。(当然,这完全是你的选择。不要因为别人这么说而被迫接受答案(例如,就像我现在说的那样))@Steve314:IIRC,SIMD指令(至少是浮点指令)有两种变体——对齐和未对齐。不过,我可能错了。对于要求所有操作一致的体系结构——大多数都要求一致(包括流行的MIPS和ARM);x86在这里是个例外。事实上
    // Assume alignof(int) --> 2
    char a[4];   // It is not known that `a` begins on an odd or even address
    int *p = a;  // conversion may fail
    int d = *p;  // *p is UB.
    
      SIZEOF_ALIGNOF(double);
      SIZEOF_ALIGNOF(complex double);
      SIZEOF_ALIGNOF(div_t);
      SIZEOF_ALIGNOF(max_align_t);
    
    8/8
    16/8
    8/4
    32/16