c# 整个数组的指针

vvppvyoh  于 2023-02-20  发布在  C#
关注(0)|答案(3)|浏览(297)
int main(){
        int a[][3]={1,2,3,4,5,6};
        int (*ptr)[3]=a;
        printf(" %d",(*ptr)[1]) ;
    }

我知道变量ptrint类型的第一个一维数组的指针,换句话说,变量ptr将存储前3个整数的地址,首先让我们假设a的基址是1000,因此我认为这个二维数组将以如下形式存储在内存中:

elements:                  |    1     |    2     |    3     ||    4     |    5     |    6     |
addressed of each element: |   1000   | 1004     | 1008     ||   1012   | 1016     | 1020     |
                           ---------------------------------||---------------------------------
addressed of each array:                1000                              1012

所以ptr会存储1000,也就是第一个数组的地址,这意味着*ptr(*ptr)[0]会给予我第一个元素的地址,*ptr+1((*ptr)[1])会给我第二个元素的地址,以此类推。
因此,据我所知,*ptr[1]将给予第二个元素的地址,而不是它的值。
但是从输出来看,我好像错了。所以我想知道我的过程中出了什么问题。

0md85ypi

0md85ypi1#

在此部分之前,您是正确的:
这意味着*ptr(*ptr)[0]会给出第一个元素的地址
(*ptr)[0]将取消引用数组指针,然后取消引用结果数组,给出第一项的值1
类似地,(*ptr)[1])将首先为您提供一个数组,然后是该数组中的第二项2
因此,据我所知,* ptr [1]将给出第二个元素的地址,而不是其值。
不,因为[]的优先级比*高,ptr[1]会先给你第二个数组(的地址),然后你解引用它,你会得到第二个数组中第一项的值4
这里的关键是,一旦你取消引用一个指向数组的指针,你就得到了一个数组--在"数组衰减"等方面就像任何数组一样。
最佳做法:

  • 如果可以避免的话,不要用*解引用数组指针。ptr[0][0]没有那么多歧义。在本例中,使用数组指针的全部意义就在于此语法。
  • 避免使用像int a[][3]={1,2,3,4,5,6};这样草率的初始化器列表。C允许这样做,但这是一种糟糕的风格,并屏蔽了一些诊断的可能性。相反,这应该是int a[][3]={ {1,2,3}, {4,5,6} };,作为奖励,它也是可读的,自文档化的代码。
pod7payv

pod7payv2#

让我们考虑调用printf时使用的表达式

printf(" %d",(*ptr)[1]) ;

首先,指针ptr指向二维数组中int[3]类型的第一个元素。

int (*ptr)[3]=a;

这是由于初始化器列表

int a[][3]={1,2,3,4,5,6};

二维数组具有两个类型为int[3]的元素。
所以解引用指针*ptr得到一个int[3]类型的左值,它是一个一维数组,然后对这个数组应用下标运算符( *ptr )[1],得到一维数组的第二个元素。
因此将输出值2
这意味着 * ptr或(* ptr)[0]将提供第一个元素的地址
表达式*ptr( *ptr )[0]是两个不同类型的实体。The expression * ptr yields lvalue of the type int [3]',使用din表达式,它可以隐式转换为指向所获得数组的第一个元素的指针。
表达式( *ptr )[0]产生所获得的int类型的数组的第一标量元素。
因此,据我所知,* ptr [1]将给出第二个元素的地址,而不是其值。
表达式ptr[1]产生二维数组的类型int[3]的第二个元素。在该表达式*ptr[1]中,所获得的类型int[3]的对象被隐式转换为类型int *的指针,并且解引用该指针产生二维数组的第二个元素的类型int的第一个元素。
为了更清楚地说明这一点,请考虑如何计算下标运算符。
例如,表达式ptr[0]等价于*( ptr + 0 ),而*( ptr + 0 )又等价于*ptr
表达式(*ptr)[1]等价于ptr[0][1]
表达式*ptr[1]等价于*(ptr[1] ),而*(ptr[1] )又等价于ptr[1][0]
一般来说,表达式ptr[i][j]可以用几种方法重写。

( *( ptr + i ) )[j]
*( *( ptr + i ) + j )
*( ptr[i] + j )
0s7z1bwu

0s7z1bwu3#

首先,启用编译器警告是一个好主意。然后你会被告知初始化器中缺少大括号。下面是你的程序的一个稍微清理过的版本:

#include <stdio.h>

int main(void)
{
    int a[][3] = {{1, 2, 3}, {4, 5, 6}};
    int (*ptr)[3] = a;
    printf("%d\n", (*ptr)[1]);
    return 0;
}

如果你运行它,你会得到输出“2”,这是因为*ptr是数组a的第一个元素,它本身是一个数组,因此(*ptr)[1]是这个包含的数组的第二个元素,它是2。

相关问题