使用C中的指针算法访问2D数组元素

时间:2017-05-31 12:05:35

标签: c arrays pointers multidimensional-array

我有这个代码,我一直试图弄清楚指针,数组组合。

int main()
{
  int s[4][2] = {
    {1234,56},
    {1212,13},
    {1434,80},
    {1312,78}
  };
  printf("%d\n",s[2]);
  printf("%d\n",*s[2]);
  printf("%d\n",s+2);
  printf("%d\n",*(s+2));
  return 0;
}

怀疑是:            即使s [2]和(s + 2)引用相同的地址,为什么*(s [2])打印该值(即1434)但*(s + 2)打印相同的地址(s +) 2)已打印。 Isn&#t; t *(s + 2)是第3个1D数组地址的平均值(即s [2] [0])?

3 个答案:

答案 0 :(得分:6)

让我们看看你的数组在内存中的外观:

+---------+---------+---------+---------+---------+---------+---------+---------+
| s[0][0] | s[0][1] | s[1][0] | s[1][1] | s[2][0] | s[2][1] | s[3][0] | s[3][1] |
+---------+---------+---------+---------+---------+---------+---------+---------+
^         ^         ^                                                           ^
|         |         |                                                           |
&s[0][0]  &s[0][1]  &s[1][1]                                                    |
|                   |                                                           |
&s[0]               &s[1]                                                       |
|                   |                                                           |
s[0]                s[1]                                                        |
|                   |                                                           |
s                   s+1                                                         |
|                                                                               |
&s                                                                              &s+1

现在让我们来s[0][0],您有五个可能指向该位置的指针:

  1. &s[0][0]。这是int *类型。
  2. &s[0]。这是int (*)[2]类型。
  3. s[0]。这将衰减为指向s[0]中第一个元素的指针,并且等于1.
  4. s。这将衰减为指向s中第一个元素的指针,并且等于2.
  5. &s。指向数组的指针,类型为int (*)[4][2]
  6. 正如你所看到的,你可以有很多不同的指针指向同一个位置,但它们可能意味着不同的东西,这在语义上会产生很大的不同。

答案 1 :(得分:0)

s [2]和(s + 2)链接到您使用简单printf查看的相同地址。 然后你有一个未定义的行为,因为%d指的是一个整数但s[2]s+2*(s+2)是指针,你必须使用引用指针的%p 。 这是你的代码:

#include <stdio.h>
int main()
{
    int s[4][2] = {
        {1234,56},
        {1212,13},
        {1434,80},
        {1312,78}
    };
    printf("%p\n",s[2]);
    printf("%d\n",*s[2]);
    printf("%p\n",s+2);
    printf("%p\n",*(s+2));
    return 0;
}

不,*(s+2)并不意味着s[2][0]它只是s的第二个元素的逻辑地址。您必须*(s[2])使用s[2][0]

答案 2 :(得分:0)

  

即使s [2]和(s + 2)引用相同的地址,为什么*(s [2])打印该值(即1434)但*(s + 2)打印相同的地址(s + 2)已打印。第3个数组的地址不是*(s + 2)的平均值(即s [2] [0])?

除了数组名称之外,

s也是数组第一个元素的指针,它是第一行。

一般来说,请记住:

s[i][j]

相当于:

*(s[i] + j)

以及:

*(*(s + i) + j)

因此s[i]相当于*(s+i)*(*(s+i) + 0)

基于这些,您可以看到:

  • s[2]*(s+2)相同,表示数组的第三个元素。这是数组第三行的地址,与数组第三行第一行的地址完全相同。
  • *(s[2])表示*(*(s+2)),表示数组第三个元素的 内容 。这是数组第三行的第一个元素的内容(即1434)。

如果您要打印s[2][0],则相当于*(*(s+2) + 0)*(*s[2])