【问题标题】:pointers and multi-dimensional arrays [duplicate]指针和多维数组
【发布时间】:2012-07-15 17:48:01
【问题描述】:

可能重复:
How do I use arrays in C++?
Is 2d array a double pointer?
Two dimensional arrays and pointers

我知道这是一个非常基本的问题,但没有多少谷歌搜索为我解决了这个问题。这就是为什么在这里发布它。 在 c++ 中考虑声明 int x[10];

这是一个一维数组,其中 x 是基指针,它包含数组第一个元素的地址。所以x 给了我那个地址,*x 给了我第一个元素。

声明类似

 int x[10][20];

这里的x是什么变量。当我这样做时

 int **z = x;

编译器说它无法将int (*)[20] 转换为int **。为什么cout<<x;cout<<*x; 给出相同的值? 而且,如果我将指针数组声明为

 int *p[10];

那么xp(在它们的类型上)之间有区别吗?因为当声明int x[10]int *p 时,将x 分配给p 是有效的,但在二维数组的情况下不是这样吗?为什么? 有人可以帮我解决这个问题,或者提供一个很好的资源材料。

【问题讨论】:

  • 这一切都可以通过阅读C FAQ on Arrays and Pointers来回答。
  • 你也可以像这样从二维数组中检索元素 *(x + 20*(row) + col),所以 x 是一个多维数组,仍然给出指向第一个值的指针

标签: c++


【解决方案1】:

数组和指针不是一回事。在 C 和 C++ 中,多维数组只是“数组的数组”,不涉及指针。

int x[10][20];

是一个由 10 个数组组成的数组,每个数组包含 20 个元素。如果你在上下文中使用x,它将衰减为指向其第一个元素的指针,那么你最终会得到一个指向那些20个元素数组之一的指针——这就是你的int (*)[20]。注意,这样的东西不是指向指针的指针,所以转换是不可能的。

int *p[10];

是一个包含 10 个指针的数组,所以是的,它与 x 不同。

特别是,您可能会遇到麻烦,因为您似乎认为数组和指针是同一件事 - 您的问题是:

这是一个一维数组,其中 x 是基指针,它包含数组第一个元素的地址。所以 x 给了我那个地址,*x 给了第一个元素。

这不是真的。一维x 是一个数组,只是在某些情况下,数组会衰减为指向其第一个元素的指针。

阅读FAQ,了解有关此主题的所有信息。

【讨论】:

  • 感谢您的回复。我现在比刚开始时清晰得多..但我仍然不明白**x 究竟是如何工作的?在这里,我们几乎使用 x 就好像它是一个指向指向第一个元素的指针的指针,对吧? coz **x 给出数组第一个元素的值。
  • @newbie,你不能在任何例子中使用**x
  • #include<iostream> using namespace std; main() { int x[10][20]; x[0][0]=11; cout<<**x<<endl; return 0; } 我的编译器为此输出 11。
【解决方案2】:

多维数组只是语法糖。在幕后,这只是一个 10 * 20 ints 长的一维数组。当您访问x[5][6] 的元素时,编译器会生成与x[5 * 20 + 6] 等效的内容;

【讨论】:

  • 这是真的,但没有回答问题。
  • @OliCharlesworth:我觉得 OP 不确定一维和多维数组之间的物理差异,并想澄清一下。由于他直接使用数组内存,因此了解数组在内存中的实际布局可能会有所帮助。
  • 访问x[5][6]应该是x[5 * 20 + 6],其中x是一个10行20列的矩阵,存储在主行中。
  • @Ritwik 你是对的。我更新了答案。谢谢。
  • 如果就这么简单,那就行了。它没有。
【解决方案3】:

这是它的真正工作原理,请查看代码和 cmets:

#include <stdio.h>

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

int (*pArr35)[3][5] = &x;
// &x is a pointer to an array of 3 arrays of 5 ints.

int (*pArr5a)[5] = x;
// x decays from an array of arrays of 5 ints to
// a pointer to an array of 5 ints,
// x is a pointer to an array of 5 ints.

int (*pArr5b)[5] = &x[0];
// &x[0] is a pointer to 0th element of x,
// x[0] is an array of 5 ints,
// &x[0] is a pointer to an array of 5 ints.

int *pInta = x[0];
// x[0] is 0th element of x,
// x[0] is an array of 5 ints,
// x[0] decays from an array of 5 ints to
// a pointer to an int.

int *pIntb = *x;
// x decays from an array of arrays of 5 ints to
// a pointer to an array of 5 ints,
// x is a pointer to an array of 5 ints,
// *x is an array of 5 ints,
// *x decays from an array of 5 ints to
// a pointer to an int.

int *pIntc = &x[0][0];
// x[0][0] is 0th element of x[0],
// where x[0] is an array of 5 ints,
// x[0][0] is an int,
// &x[0][0] is a pointer to an int.

int main(void)
{
  printf("&x=%p x=%p &x[0]=%p x[0]=%p *x=%p &x[0][0]=%p\n",
         pArr35, pArr5a, pArr5b, pInta, pIntb, pIntc);
  return 0;
}

样本输出:

&x=0040805c x=0040805c &x[0]=0040805c x[0]=0040805c *x=0040805c &x[0][0]=0040805c

所有结果指针在值方面都是相同的,因为我显式或隐式使用了 0 的索引,并且因为数组是连续的,并且它们的第一个(IOW,第 0 个)元素始终位于数组中的最低地址。因此,即使有 3 种不同的指针类型,它们都有效地指向 x[0][0],指向等于 1 的元素。

数组到指针的这种衰减是 C 和 C++ 的一个非常重要的特性,尽管很难立即掌握。

它让我们在向数组传递指针时可以编写更紧凑的代码,我们可以只写数组的名称而不是获取其第一个元素的地址:

char str1[] = { 's', 't', 'r', '1', '\0' };
char str2[] = "str2";
printf("%s %s %s %s\n", &str1[0], str1, &str2[0], str2);

输出:

str1 str1 str2 str2

它还可以让我们做一些疯狂的事情:

int y[3] = { 10, 20, 30 };
printf("%d %d %d %d\n", y[2], *(y+2), *(2+y), 2[y]);

输出:

30 30 30 30

因为a[b] 在数组和指针方面等同于*(a+b)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-04-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-02
    相关资源
    最近更新 更多