简体   繁体   English

C 编程 2D 阵列存储器布局

[英]C programming 2D array memory layout

Consider the c code below.考虑下面的 c 代码。

#include <stdio.h>
int main(){
   unsigned int x[4][3] = {{1, 2, 3}, {4, 5, 6},
                       {7, 8, 9}, {10, 11, 12}};
   printf("%u, %u, %u", x+3, *(x+3), *(x+2)+3);
   printf("\n%u, %u, %u", x,&x,*x);
   return 0;
}

Now each of the printf statement prints the same values as mentioned below.现在,每个 printf 语句都打印出与下面提到的相同的值。

6356724, 6356724, 6356724
6356688, 6356688, 6356688
Process returned 0 (0x0)   execution time : 0.128 s
Press any key to continue.

I wanted to know how is the outcome same in each printf statements.我想知道每个 printf 语句的结果如何相同。 This is my understanding of memory layout of 2-D array.这是我对二维数组内存布局的理解。 二维阵列内存布局

Now I believe x+3 refers to base address of( x + 3 * size require for pointer arithmetic ) = 24 and *(x +3 ) = *(24) = 2036 but its not the case the first printf statement prints 2036, 2036 2036 .现在我相信 x+3 是指 ( x + 3 * 指针运算所需的大小 ) = 24 和 *(x +3 ) = *(24) = 2036 的基地址,但不是第一个 printf 语句打印 2036 的情况, 2036 2036。 I wanted to visually understand how exactly 2-D array is organized.我想直观地了解二维数组是如何组织的。

Whenever an array is mentioned, it decays to a pointer to its first element (except in a few cases that are not interesting right now).每当提到一个数组时,它都会衰减到指向其第一个元素的指针(除了一些现在不感兴趣的情况)。

Why x , &x and *x are all printed the same?为什么x&x*x都打印相同? That's because the array itself, its first element, (and if it's a 2D array, the first element of its first element, which is by itself a 1D array) all have the same address.这是因为数组本身,它的第一个元素(如果它是一个二维数组,它的第一个元素的第一个元素,它本身就是一个一维数组)都具有相同的地址。

So:所以:

  • &x is the pointer to the array &x是指向数组的指针
  • x is the array itself, which decays to the pointer of its first element x是数组本身,它衰减到其第一个元素的指针
  • *x is the first element of the array, which is itself an array (1, 2, 3} , so it decays to the pointer of its first element *x是数组的第一个元素,它本身就是一个数组(1, 2, 3} ,所以它衰减到它的第一个元素的指针

All these pointers have different types, but point to the same address.所有这些指针都有不同的类型,但指向相同的地址。

The same thing happens with x+3 and *(x+3) .同样的事情发生在x+3*(x+3) First, x decays to a pointer, then pointer arithmetic is performed.首先, x衰减为一个指针,然后执行指针运算。 Say y = x + 3 , so y and *y point to the same address just as x and *x` do (see above).假设y = x + 3 ,因此y*y指向与x和 *x` 相同的地址(见上文)。

What about *(x+2)+3 ? *(x+2)+3呢? Well, *(x + 2) is itself is an array of 3 elements.好吧, *(x + 2)本身就是一个包含 3 个元素的数组。 So *(x+2)+3 points to one element past the end of the *(x + 2) array.所以*(x+2)+3指向超过*(x + 2)数组末尾的一个元素。 This non-existing element has an address nevertheless , and it is the same as the address of the first element of the *(x + 3) array --- because *(x + 2) and *(x + 3) are next to each other in the x array.这个不存在的元素仍然有一个地址,它与*(x + 3)数组的第一个元素的地址相同 --- 因为*(x + 2)*(x + 3)是下一个在x数组中相互关联。

I'll try to explain from a layman's point of view.我将尝试从外行的角度进行解释。

Let us assume the base address is 3000, and assume that integer takes 4 bytes.让我们假设基地址是 3000,并假设整数占用 4 个字节。

Considering your 2-D array, this is how WE visualise a 2-D array in the memory :考虑到您的二维数组,这就是我们在内存中可视化二维数组的方式:

         0                       1                2
     --------------------------------------------------
  0 |   1                |    2           |   3          |
    | 3000/3001/3002/3003| 3004/05/06/07  | 3008/09/10/11|
    |___________________ |________________|______________|                      
  1 |    4               |    5           |   6          |
    |   3012             |    3016        |   3020       |
    |____________________|________________|______________|                      
  2 |    7               |    8           |   9          |
    |    3024            |    3028        |   3032       |
    |____________________|________________|______________|                      
  3 |     10             |   11           |   12         |
    |    3036            |   3040         |   3044       |
    |                    |                |              |
    ------------------------------------------------------

Now, you should know how a 2-D array is actually stored just like a 1-D array in the memory:现在,您应该知道二维数组实际上是如何像一维数组一样存储在内存中的:

index    0       1       2      3     4      5     6      7      8      9      10    11  

        ---------------------------------------------------------------------------------
       |  1   |  2   |  3   |  4   |  5   | 6   |  7   |  8   |  9   |  10  |  11 |  12  |       
       |      |      |      |      |      |     |      |      |      |      |     |      |
add.   |3000__|_3004_|_3008_|_3012_|_3016_|_3020|3024__|_3028_|3032__|_3036_|_3040|3044_ |

Now, your code says:现在,您的代码说:

printf("%u, %u, %u", x+3, *(x+3), *(x+2)+3);

(i) x+3 (一) x+3

Here x is your base address, which is 3000(assumed), and +3 means the 3rd row.这里 x 是你的基地址,它是 3000(假设),+3 表示第三行。 Since there is nothing after that,ie, x+3, we will find out the address of the first element of the 3rd row.由于之后没有任何内容,即x+3,我们将找出第3行第一个元素的地址。

=3000+36=3036 =3000+36=3036

(refer the 2D array visualisation that WE see, the first one) (参考我们看到的二维数组可视化,第一个)

(ii) *(x+3) (ii) *(x+3)

This is the same as x+3, ie, we have to find the address of the first element of the third row.这与 x+3 相同,即我们必须找到第三行的第一个元素的地址。 I say the first element because if something was mentioned after *(x+3)+'something', then we would be concerned about finding it.我说第一个元素是因为如果在 *(x+3)+'something' 之后提到了什么,那么我们会担心找到它。

=3000+36=3036. =3000+36=3036。

(refer the 2D array visualisation that WE see, the first one) (参考我们看到的二维数组可视化,第一个)

(iii) *(x+2)+3 (iii) *(x+2)+3

Just for understanding , let us break this into two parts.只是为了理解,让我们把它分成两部分。

First, *(x+2): as we have seen in the above two parts, *(x+2) says that "I have started from the base address, now give me the address of the first element of the 2nd row. So, we reach element with value 7 and address 3024 . (refer the 2D array visualisation that WE see, the first one)首先,*(x+2):正如我们在上面两部分中看到的,*(x+2)表示“我已经从基地址开始,现在给我第2行第一个元素的地址。因此,我们到达值为 7 且地址为 3024 的元素(参考我们看到的二维数组可视化,第一个)

Second, +3 as in *(x+2)+3 means that since we have reached element with value 7 and address 3024, now see/move to the 3rd element after the element with value 7 and address 3024 (where we are right now).其次,*(x+2)+3 中的 +3 表示由于我们已经到达值为 7 且地址为 3024 的元素,现在查看/移动到值为 7 且地址为 3024 的元素之后的第三个元素(我们是对的)现在)。 So, we move past/see-through elements with values 8 and 9, with addresses 3028 and 3032 respectively, and reach/land on the element with value 10 and address因此,我们移动过去/透视元素的值为 8 和 9,地址分别为 3028 和 3032,并到达/降落在值为 10 和地址的元素上

=3000+36=3036 =3000+36=3036

(refer the 2D array visualisation that WE see, the first one) (参考我们看到的二维数组可视化,第一个)



For your second code:对于您的第二个代码:

 printf("\n%u, %u, %u", x,&x,*x);

I go with @ n.我和@n一起去 'pronouns' m. '代词' m. answer.回答。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM