C++ 意外的MPI地址偏移

C++ 意外的MPI地址偏移,c++,mpi,C++,Mpi,在下面的代码中,我希望addr[2]-addr[1]等于4x4=16,这是由block\u count[1]*extent\u int给出的答案。为什么addr[2]-addr[1]20 #include <mpi.h> #include <iostream> struct S { int a; int nei[4]; double point[4]; }; int main() { MPI_Init(NULL, NULL);

在下面的代码中,我希望
addr[2]-addr[1]
等于
4x4=16
,这是由
block\u count[1]*extent\u int
给出的答案。为什么
addr[2]-addr[1]
20

#include <mpi.h>
#include <iostream>

struct S
{
    int a;
    int nei[4];
    double point[4];
};

int main()
{
    MPI_Init(NULL, NULL);

    S s;

    int nblock = 3;
    // block count.
    int block_count[nblock] = {1, 4, 4};
    // extent.
    MPI_Aint lb, extent_int;
    MPI_Type_get_extent(MPI_INT, &lb, &extent_int);
    // offset.
    MPI_Aint addr[nblock];
    MPI_Get_address(&s.a, &addr[0]);
    MPI_Get_address(&s.nei[0], &addr[1]);
    MPI_Get_address(&s.point[0], &addr[2]);
    //
    std::cout << addr[1]-addr[0] << "  " << block_count[0]*extent_int << std::endl;
    std::cout << addr[2]-addr[1] << "  " << block_count[1]*extent_int << std::endl;

    MPI_Finalize();

    return 0;
}

这与MPI无关。在具有平坦地址空间(基本上是任何现代操作系统)的体系结构上
MPI\u Get\u address(&a和&b)相当于
b=(MPI_Aint)&a您只需观察(如@弗兰西斯指出的)C++编译器插入填充,以满足平台的默认对齐规则。其余部分在(由@francis提供的链接)的答案中进行了描述

有一个相对简单的规则来防止此类结构的错位和相关尺寸的增加:在开始时放置(如果可能)最大的类型:

struct S
{
   double point[4];
   int a;
   int nei[4];
};

由于
int
的大小除以
double
的大小,因此
int
将对齐,在这种情况下不会添加填充。这同样适用于代码中的局部变量,一些编译器会在代码优化过程中重新排列它们。

这似乎与对齐有关。看见特别是在这里,结构开头和double数组之间的空间是24字节,是8的倍数。
struct S
{
   double point[4];
   int a;
   int nei[4];
};