通过C中的数组名称和指针访问2D数组元素

时间:2019-01-04 16:02:09

标签: c arrays pointers multidimensional-array

我对2D阵列有点困惑。特别是使用公式 a[i][j] = *(*(a+i)+j)  在提出疑问之前,我想谈谈我对符号'*''&'的看法。我认为'&'是一个运算符,它以“变量”作为操作数并给出“变量的地址”,而'*'是将“变量地址”作为操作数并给出“变量”作为输出,所以/ p>

1.*(address)---->>(gives variable)

2.&(variable)---->>(gives address)

(请告诉我这个概念是否错误)

现在假设有一个二维数组“ a”,如下所示:

a[3][2]={{1,2,3},{4,5,6},{7,8,9},{10,11,12}}

现在,我想使用该公式访问数组块的最后一个元素,即a[3][2]

第一个疑问

所以按公式:

 a[3][2]=*(*(a+3)+2) // 1

我已阅读到a + 3给出了4rt行的第一个元素的地址,即&a[3][0]。 但是我见过有人说写a等效于&a[0][0]。因此代入方程式(1)

a[3][2] *(*(&a[0][0] +3)+2)

因此,在&a[0][0]上加3表示对块a[1][0] .....(在a[0][0]前面的三个块)进行地址分配。因此,这里我们的(a + 3)已将我们指向&a[1][0],而不是&a[3][0]

第二个疑问

假设现在求值(a + 3)确实给了我a [3] [0]的地址(正确)。所以等式(1)现在变为

a[3][2]=*(*(&a[3][0])+2)

使用我的概念

*(address of variable)---->>(gives variable)

所以*(&a[3][0])= a[3][0]。因此a [3] [0]应该是一个存储值10的变量。现在,我们有了a[3][2]=*(10+2)=*(12)。但是,现在'*'运算符需要地址作为输入,并且我们给出的r值不是地址,因此应该给出错误。

我知道我的概念中有很多错误,但是我是一个初学者,刚开始使用C语言作为我在编程领域的第一个话题,请帮帮我。

1 个答案:

答案 0 :(得分:1)

  

我认为'&'是一个将变量作为操作数并给出该变量地址的运算符...

这不是很正确。我们应该澄清什么是“变量”。在C语言中,通常称为变量的是标识符和对象。标识符是我们用作名称的文本字符串。例如,在int xyz;中,“ xyz”是标识符。对象是用于表示值的内存区域。因此,在int xyz;中,对象是编译器在内存中保留的几个字节(通常是四个字节)。

&运算符提供了将其应用于的对象(或函数)的地址。请注意,不必将其应用于变量,只需将其应用于任何对象(或函数)即可。因此,代替命名对象,它可以应用于某些计算对象(如&a[i+4])或字符串文字(&"abc")或复合文字(& (int []) {3, 4, 5})。

  

…和'*'可逆地将变量的地址作为操作数,并将变量作为输出,

*使用指向对象(或函数,在此不再讨论)的指针,并生成对象(具体来说,是指定该对象的左值)。该对象不必是命名变量的对象。它可以是数组元素,也可以是动态分配的对象或其他任何东西。

  

现在假设有一个二维数组“ a”,如下所示:

     

a [3] [2] = {{1,2,3},{4,5,6},{7,8,9},{10,11,12}}

这不是正确的数组定义,因为它没有元素类型,并且因为它说数组的维数是3和2,但是初始化程序列表显示的维数应该是4和3。让我们假设将其更正为:

int a[4][3] = { {1, 2, 3}, {4, 5, 6}, {7, 8, 9}, {10, 11, 12} };
  

我已经读到a + 3给出了第四行的第一个元素的地址,即&a [3] [0]。

不完全是。在表达式a+3中,a指定一个数组。该数组会自动转换为指向其第一个元素的指针,因此它等效于&a[0]。请注意,此表达式的类型是3 int的数组-它是a的子数组。当我们加3时,编译器将计数3个子数组,因此a+3指向子数组编号3(从0开始编号)。因此a+3等效于&a[3]

&a[3]是第3个子数组的地址。这与&a[3][0]是第3个子数组的元素号0的地址不同。尽管它们实际上指向了在内存中的同一位置,它们具有不同的类型,并且编译器将它们区别对待。

  

但是我看到有人说写a等同于&a [0] [0]。

那是不正确的。 a等效于&a[0],它是指向a第一个元素的指针。 a的第一个元素本身是一个数组;它是a[0],而不是a[0][0]。尽管&a[0]&a[0][0]实际上可以指向内存中的相同位置,但是它们具有不同的类型,并且编译器将对它们进行不同的处理。

  

所以代入公式(1)

由于a不等同于&a[0][0],因此不能用后者代替前者。

让我们回到您提到的公式:

  

a [i] [j] = *(*(a + i)+ j)

这是正确的。回想一下,a会自动转换为&a[0]。然后&a[0]+ii个子数组进行计数,加法的结果等于&a[i]。然后,在*(a+i)中,我们应用*运算符。这会将&a[i]更改为*&a[i]。由于&a[i]指向a[i],所以*&a[i]a[i]

现在,我们已经确定*(a+i)变成a[i],并且我们想知道*(a+i)+j是什么。实际上,我们在问a[i]+j是什么。因此,我们必须弄清楚此表达式中a[i]会发生什么。

回想一下a[i]a的子数组。因此它本身就是一个数组。在表达式中使用数组时,数组会自动转换为其第一个元素的地址(用作sizeof或一元&的操作数时除外)。因此a[i]被转换为&a[i][0]。然后,我们添加j,生成&a[i][0] + j。由于&a[i][0]是指向int的指针,因此编译器对j int进行计数并生成指向a[i][j]的指针。也就是说,*(a+i)+j的结果是&a[i][j]。然后应用*会产生*&a[i][j],即a[i][j]