取消引用数组名称

Dereference array name

根据我的理解,数组名不是变量, 那么我们怎么可能像这样取消引用它:

int a[] = {1,2,3,4,5};
void *p = &a;

这是什么意思? 以及为什么我们所有的 MPI 函数都需要这种取消引用?

 int buff[2];
 ...  
 MPI_Bcast(&buff, 2, MPI_INT, PROC, MPI_COMM_WORLD);

来自 Kernighan & Ritchie:

There is one difference between an array name and a pointer that must be kept in mind. A pointer is a variable, so pa=a and pa++ are legal. But an array name is not a variable; constructions like a=pa and a++ are illegal.

"array name" 不存在。可以有一个指向数组第一个元素的指针类型的命名变量。

int a[] = {1,2,3,4,5};
void *p = &a;

a是一个int类型的指针,指向第一个元素“1”。 p是一个void指针,赋值后实际指向的是数组第一个元素所在的地址。

我不知道你们的图书馆是怎么运作的。通常,如果您调用的函数应该能够修改指针,则使用此模式。例如,当库分配一个新数组并更新指针引用时,这就是 "useful"。我在引号中写的很有用,因为我认为这不是很好的做法。

数组是一个变量,但它不能赋值给(你不能"move the array")。

在许多上下文中,名称的计算结果为数组第一个元素的地址,但它不等同第一个元素的地址。

您可以在数组名称上使用 sizeof 并获取数组的实际大小(以字节为单位),如果名称等同于指针,则这是不可能的。像这样:

int a[4];

printf("the array a has size %zu\n", sizeof a);

在 8 位 char 和 32 位 int 的机器上,以上将打印 16。这证明名称 a 指的是 而不是 只是一个指针。

所有 MPI 函数都采用作为 void * 提供的消息缓冲区的开头地址。它们不需要类型化指针,因为有关缓冲区内存布局的所有信息均由 MPI 数据类型提供,在这种情况下 MPI_INT.

int buff[2];
...  
MPI_Bcast(&buff, 2, MPI_INT, PROC, MPI_COMM_WORLD);

这段代码在技术上是错误的。 &buff 是类型 int (*)[2] 的表达式,即指向两个整数元素的数组的指针。尽管它计算出与 buff 相同的地址,但它在指针运算方面具有不同的语义。

正确的表达方式应该是:

MPI_Bcast(buff, 2, MPI_INT, PROC, MPI_COMM_WORLD);

MPI_Bcast(&buff[0], 2, MPI_INT, PROC, MPI_COMM_WORLD);

传递 &buff 也是危险的,因为稍后可能决定动态分配 buff 而不是静态分配,例如int *buff = malloc(2 * sizeof(int));现在&buff不会指向分配内存的开始,而是指向指针所在的地址,这是完全错误的,MPI不执行指针追逐。如果使用 buff&buff[0],则不会发生这种情况。

此外,请注意 &address-of 运算符,即它 returns 是一个引用。要取消引用,请使用 * 运算符。