【问题标题】:Dereference array name取消引用数组名称
【发布时间】:2015-06-13 07:03:19
【问题描述】:

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

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:

数组名和指针之间有一个区别 请牢记。指针是一个变量,所以 pa=a 和 pa++ 是合法的。 但是数组名不是变量;像 a=pa 和 a++ 这样的结构 是非法的。

【问题讨论】:

  • “数组名不是变量”是什么意思?在对MPI_Bcast的调用中,buff的类型是什么?
  • 数组名是指向其第一个元素的指针。所以,a==&a[0]
  • 是的,很酷的家伙,我知道,但这不是一个变量。
  • 是指针类型的变量。

标签: c arrays pointers mpi


【解决方案1】:

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

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

此代码在技术上是错误的。 &buffint (*)[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 运算符,即它返回一个引用。要取消引用,请使用 * 运算符。

【讨论】:

    【解决方案2】:

    “数组名称”不存在。可以有一个指针类型的命名变量,它指向数组的第一个元素。

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

    a 是指向第一个元素“1”的 int 类型的指针。 p 是一个空指针,赋值后它实际上指向了存储数组第一个元素地址的位置。

    我不知道你的图书馆是如何运作的。通常,如果您调用的函数应该能够修改指针,则使用此模式。例如,当库分配一个新数组并更新指针引用时,这是“有用的”。我在引号中写有用,因为我不认为这是一种好习惯。

    【讨论】:

    • 不,a 肯定不是“int 类型的指针”,它是一个数组。它的类型是int[5]。考虑printf("the size is %zu\n", sizeof a); 的工作原理。
    • 从语法上讲,我同意。语义上,是不是真的一样?
    • C 标准非常清楚什么意思:“除非它是 sizeof 运算符或一元 & 运算符的操作数,或者是用于初始化数组的字符串文字,类型为“type 的数组”的表达式被转换为类型为“pointer to type”的表达式,它指向数组对象的初始元素,而不是一个左值。”
    【解决方案3】:

    数组是变量,但不能赋值(不能“移动数组”)。

    在许多情况下,名称计算为数组第一个元素的地址,但它与第一​​个元素的地址等效

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

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

    在具有 8 位 char 和 32 位 int 的机器上,上面将打印 16。这证明了名称a 所指的东西只是一个指针。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-07-06
      • 1970-01-01
      • 1970-01-01
      • 2012-11-27
      • 1970-01-01
      • 2017-12-29
      • 2021-02-08
      • 2014-01-11
      相关资源
      最近更新 更多