【问题标题】:Double Pointer to Array in CC中指向数组的双指针
【发布时间】:2021-04-06 11:35:53
【问题描述】:

下面是代码 sn-p 和输出:

int main() 
{
    int A[2][3] = {{1100, 1200, 1300}, {1400, 1500, 1600}};
    int (*p)[3], (**q)[3];
    p = A;
    q = A;
    printf("*p is : %d\n", *p);
    //Output : *p is : -547221600
    printf("*q is : %d", *q);//Why ?  
    //Output : *q is : 1100 
}

p 是一个指向大小为 3 的整数数组的指针。*p + i 指向 A 中的第 i 个数组,即 A[i]。 如果我改为使用双指针(上面代码中的q)会发生什么。 我无法理解为什么 *q 给出 1100 作为值。

【问题讨论】:

  • TL;DR。 int (**)[3] 只能用于指向int (*)[3] 类型的_pointers,所以它并不是那么有用。关于此类指针的唯一有效用途是在通过函数参数返回指向数组的指针时,例如void allocate(size_t x, size_t y, int (**p)[x][y]) { *p = malloc(sizeof (int [x][y])); }

标签: c pointers c99


【解决方案1】:

对于初学者这个作业

q = A;

不正确,因为左操作数(类型为int ( ** )[3])和右操作数(类型为int ( * )[3],在数组指示符隐式转换为指向其第一个元素的指针后)具有不同的类型,并且存在类型之间没有隐式转换。

编译器会发出这样的错误

error: assignment to ‘int (**)[3]’ from incompatible pointer type ‘int (*)[3]’

你可以改写

q = &p;

在这次printf的电话中

printf("*p is : %d\n", *p);

使用了不正确的参数。表达式*p 的类型是int[3]。因此,实际上您正在尝试使用旨在输出整数的转换说明符%d 输出一个指针(由于数组指示符隐式转换为指向其第一个元素的指针)。

这是一个演示程序。

#include <stdio.h>

int main(void) 
{
    int A[2][3] = {{1100, 1200, 1300}, {1400, 1500, 1600}};
    int (*p)[3], (**q)[3];
    p = A;
    q = &p;
    
    printf( "A  is : %p\n", ( void * )A );
    printf( "*p is : %p\n", ( void * )*p );
    printf( "*q is : %p\n", ( void * )*q);
    
    return 0;
}

它的输出可能看起来像

A  is : 0x7ffdb1c214e0
*p is : 0x7ffdb1c214e0
*q is : 0x7ffdb1c214e0

即第一次调用printf输出二维数组第一个元素A[0](类型为int[3])的起始地址。

第二次调用printf输出二维数组第一“行”的第一个元素的地址,即&A[0][0]。

第三次调用 printf 输出存储在指针p 中的值,即二维数组 A 的第一“行”的地址。

如果你想使用指针输出数组 A 的第一个元素,那么程序可以如下所示。

#include <stdio.h>

int main(void) 
{
    int A[2][3] = {{1100, 1200, 1300}, {1400, 1500, 1600}};
    int (*p)[3], (**q)[3];
    p = A;
    q = &p;
    
    printf( "**p  is : %d\n", **p );
    printf( "***q is : %d\n", ***q);
    
    return 0;
}

现在程序输出是

**p  is : 1100
***q is : 1100

【讨论】:

  • 技术上的“不同类型”并不一定意味着赋值不正确,因为该语言具有隐式转换。有问题的赋值不正确,因为没有从右侧操作数到左侧的隐式转换。
  • 我使用的在线IDE没有给出q = A的错误。那么,为什么*q会返回1100作为输出?是不是编译器出现了意外的行为?
  • @VarunSaproo 在无效语句 q = A 之后,程序具有未定义的行为。
【解决方案2】:

p 是一个指向大小为 3 的整数数组的指针。

正确。

*p + i 指向 A 中的第 i 个数组,即 A[i]。

不正确。 p + i 将是一个指向数组的指针。

当你间接通过指向数组的指针时,结果是一个数组,当你向数组添加一个整数时,数组衰减为指向该数组元素的指针,因为*p是一个整数数组,衰减指针指向数组的整数元素。因此,*p + i 的结果是一个指向整数(第一个数组的第一个元素的第 i 个兄弟)的指针。

如果我改为使用双指针(上面代码中的 q)会发生什么。

我假设通过替换上面的代码,你的意思是*q + i

如果您有一个指向数组指针的指针,那么通过指针间接生成指向数组的指针。将整数添加到指向数组的指针会为您提供指向同级数组的指针。


q = A;

这个赋值在 C++ 中格式不正确。整数数组的数组不能转换为指向数组的指针。

printf("*p is : %d\n", *p);
printf("*q is : %d", *q);//Why ?  

%d 是 int*int (*)[3] 的无效格式说明符。通过使用无效的格式说明符,该程序的行为是未定义的。这解释了所有的行为。

【讨论】:

    猜你喜欢
    • 2021-05-29
    • 1970-01-01
    • 1970-01-01
    • 2012-11-17
    • 1970-01-01
    • 2017-08-25
    • 2013-04-19
    • 1970-01-01
    相关资源
    最近更新 更多