2016-07-05 43 views
-1
#include<bits/stdc++.h> 
using namespace std; 
int main() 
{ 
    int a[101][101]; 
    a[2][0]=10; 
    cout<<a+2<<endl; 
    cout<<*(a+2)<<endl; 
    cout<<*(*(a+2)); 
    return 0; 
} 

为什么a + 2和*(a + 2)的值相同?提前致谢!2维数组如何存储在内存中?

+2

可能只是巧合,如果你相信那样的事情...... –

+0

即使打印的指针值相同,类型也不一样。 – Jarod42

+1

你很幸运!今天,只有今天,在stackoverflow.com我们有一个特别的去:回答你自己的问题!创建一个小数组,例如'int a [2] [2]'。将四个值放入它中,比如说1,2,3和4.获取一个指向第一个元素的指针,“int * p =&a [0] [0];'。然后用调试器查看'p'指向什么,并回答你自己的问题。这真是个便宜货!! –

回答

4

a是一个二维数组,这意味着一个数组的数组。但它衰退当在适当的上下文中使用一个指向数组的指针。所以:

  • a+2a衰减到指针时被传递到一个ostream,则得到此数组的第一元素的地址为int大小101的阵列,即&(a[2][0])
  • *(a+2)的定义a[2]:它是一个大小为101的数组,起始于a[2][0]。它衰变到一个指针为int,而当你把它传递给你的第一个元素的地址一个ostream,这仍然是&(a[2][0])
  • **(a+2)定义a[2][0]。当你把它传递给一个ostream你得到它的int值,这里10

但要注意:a + 2a[2]都指向同一个地址(static_cast<void *>(a+2)相同static_cast<void *>(a[2])),但它们指向不同类型:首先指向大小为101的int数组,后者为int。

+0

谢谢!这非常有帮助。 – Shubham

1

A 2维数组是数组的数组,所以它的存储像这样在存储器中:

char v[2][3] = {{1,3,5},{5,10,2}}; 

Content: | 1 | 3 | 5 | 5 | 10 | 2 
Address: v v+1 v+2 v+3 v+4 v+5 

要访问v [X] [Y],编译器重写它为:*(v + y * M + x)(其中,M在第二尺寸指定)

例如,访问v [1] [1],编译器重写它作为*(v + 1*3 + 1) =>*(v + 4)

注意,这是不相同作为指针(char **)的指针。 指向指针的指针不是数组:它包含并寻址到包含另一个地址的存储单元。

访问使用指针的指针2维阵列的构件,这是已完成:

char **p; 
/* Initialize it */ 
char c = p[3][5]; 
  1. 转到由p内容所指定的地址;
  2. 将偏移量添加到该地址(在我们的例子中为3);
  3. 转到该地址并获取其内容(我们的新地址)。
  4. 将第二个偏移量添加到该新地址(在我们的例子中为5)。
  5. 获取该地址的内容。

虽然经由传统的2维数组的访问部件,这些步骤如下:

char p[10][10]; 
char c = p[3][5]; 
  1. 获取的p地址和综所述第一偏移量(3)中,由该相乘一行(10)的尺寸。
  2. 将第二个偏移量(5)添加到结果中。
  3. 获取该地址的内容。
1

如果有这样

T a[N]; 

然后阵列的名称被隐式转换为指向其除了极少数例外第一元件的阵列(如例如在sizeof操作者使用阵列名称)。

因此,例如在表达式(a + 2)a是转换类型T *的值&a[0]

相对于你的例子wuth阵列

int a[101][101]; 

在表达

a + 2 

一个被转换成int (*)[101]类型并指向阵列的第一“行”的右值。 a + 2指向阵列的第三个“行”。该行的类型是int[101]

表达式*(a+2)给出了此第三行的类型为int[101],这是一个数组。并且这个数组在表达式中依次被转换为它的第一个元素的指针int *

它与第三行占用的内存区域的起始地址相同。

只有表达(a + 2)具有类型int (*)[101]而表达*(a + 2)具有类型int *。但是这两者产生相同的值 - 数组的第三行占用的内存区域的起始地址a

+0

谢谢!这非常有帮助。 – Shubham

0

数组的第一个元素与数组本身位于同一位置 - 数组中没有“空白空间”。

cout << a + 2a被隐式转换成一个指向它的第一元件,&a[0]a + 2a的第三元件,&a[2]的位置。

cout << *(a + 2)中,数组*(a + 2) - 即a[2] - 被转换为指向其第一个元素&a[2][0]的指针。

由于a的第三个元素的位置和a的第三个元素的第一个元素的位置相同,所以输出是相同的。

0

我会尽力解释你如何内存是由编译器映射:

让我们考虑一个更加之实践例子多维数组:

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

您可以执行命令

x/10w a 

在GDB中看看内存:

0x7fffffffe750: 1 2 3 4 
0x7fffffffe760: 5 6 7 8 
0x7fffffffe770: 9 0 

每个元素都存储在一个int类型(32位/ 4字节)。 所以矩阵的第一个元素已被存储在:

1) a[0][0] -> 0x7fffffffe750 
2) a[0][1] -> 0x7fffffffe754 
3) a[0][2] -> 0x7fffffffe758 
4) a[1][0] -> 0x7fffffffe75c 
5) a[1][1] -> 0x7fffffffe760 
6) a[1][2] -> 0x7fffffffe764 
7) a[2][0] -> 0x7fffffffe768 
     ... 

的命令:

std::cout << a + 2 << '\n' 

它将打印,因为该 指针aritmetic的地址0x7fffffffe768: 类型的一个int **所以它是一个指向指针的指针。 a + 2是a [0](第一行)+2。结果是指向第三行的指针 。

*(A + 2)deferences第三行,这是{7,8,9}

第三行是int数组,这是为int的指针。

然后运营商< <将打印该指针的值。

+0

在这个例子中,不是'a'实际上'int [3] [3]'的类型吗? – wally

+0

@flatmouse你是对的。更准确的说这个类型是int [3] [3],这是因为大小是静态的,编译时间。 –