int main(){
int a[10][10];
int **ptr =(int **)a;
cout<<a<<endl<<ptr<<endl;
cout<<*a<<endl<<*ptr<<endl;
return 0;
}
在我的电脑上输出此代码
0021FC20
0021FC20
0021FC20
CCCCCCCC
为什么“ a ”等于“ * a ”? 为什么不等于* ptr?
答案 0 :(得分:4)
为什么
a
等于*a
?
在需要指针的上下文中使用时,数组将转换为指向其第一个元素的指针。 a
是一个数组数组;所以它会衰减到指向第一个数组的指针。 *a
是第一个数组,并将衰减为指向该数组中第一个整数的指针。这两个都存在于同一个位置,因此两个指针的值相等。
为什么不等于* ptr?
因为从数组数组到指针指针的转换无效。您已使用强制转换强制转换 - 这是一种危险的C样式转换,在这种情况下就像reinterpret_cast
一样 - 所以*ptr
将读取数组的前几个字节并将其解释为指针(可能 - 这里的行为是未定义的,因此原则上任何事情都可能发生。 ptr
指向的内存中没有指针,因此*ptr
肯定不会给你一个有效的指针。
答案 1 :(得分:2)
为什么等于* a?
由于您无法打印数组,a
会从int[10][10]
隐式转换为int(*)[10]
。那么实际打印而不是a
的是指向a
的第一个行的指针。
*a
是数组的第一行,然后转换为指向第一个元素的指针。
由于数组与第一个元素具有相同的地址,因此两次获得相同的值。
答案 2 :(得分:1)
然后我建议避免使用大型矩阵的静态堆栈分配,而选择动态分配(在堆上)......
答案 3 :(得分:1)
2D阵列的机制实际上比它们第一次出现时更容易,但它通常很难教。然而,快速解读事物确实需要很多经验,即使是经验丰富的开发人员有时也必须停下来思考片刻(或两点)。基本上,当你看到一个2D数组,如int a [5] [10](我将数组的大小改为5以简化事物),你需要不再把它当作2D。可以把它想象为1D。第一个下标指定此1D数组中的元素数,就像任何其他1D数组一样。当您索引数组时,例如[3],您将访问索引3处的对象。这与任何其他数组没有什么不同。让我们说“a”的定义是这样的:
// Note: The size of the array, 5, can be omitted
int a[5] = {5, 10, 15, 20, 25};
订阅然后产生这个:
a[0] = 5
a[1] = 10
a[2] = 15
a[3] = 20
a[4] = 25
这很容易,而且大多数都可以。但是,如果你现在这样做:
// Note: Like above, the size of the array, 5, can be omitted
int a[5][10] = {{ 5, 10, 15, 20, 25, 30, 35, 40, 45, 50},
{ 55, 60, 65, 70, 75, 80, 85, 90, 95, 100},
{105, 110, 115, 120, 125, 130, 135, 140, 145, 150},
{155, 160, 165, 170, 175, 180, 185, 190, 195, 200},
{205, 210, 220, 225, 230, 235, 240, 245, 250, 255}};
你仍然有一个1D数组,你可以像上一个例子一样下标,产生以下内容(不是真正的语法,你应该怎么想):
a[0] = 5 10 15 20 25 30 35 40 45 50
a[1] = 55 60 65 70 75 80 85 90 95 100
a[2] = 105 110 115 120 125 130 135 140 145 150
a[3] = 155 160 165 170 175 180 185 190 195 200
a[4] = 205 210 220 225 230 235 240 245 250 255
这里唯一的区别是,与前一个示例相比,每个元素都是一个“int”,而不是每个元素都是一个数组(10个整数)。因此,当您看到它时,每个索引(0到4)返回该行的10个整数数组。例如,a [3]返回包含值155到200的10个整数的数组。元素本身是“int [10]”,因此您可以这样对待它。 IOW,你得到了相当于这个:
int b[10] = {155, 160, 165, 170, 175, 180, 185, 190, 195, 200};
因此,例如,以b [7] = 190,a [3] [7] = 190的相同方式,因为a [3]实际上返回b的等价物(10的数组)整数),[7]下标然后抓住该数组的索引7处的元素,就像b [7]。而且,就像b是指向数组的第一个元素的指针一样(因为所有的数组名都衰变成指向数组的第一个元素的指针),在这种情况下是155,a [3]也做了一样。为什么?因为它正如所描述的那样返回b的等价物,就像b一样,它衰变成指向其第一个元素的指针。 IOW,就像这样:
int *p = b; // "b" decays into a pointer to its first element (an "int")
int val = *p; // Equals 155
这也是如此:
int *p = a[3]; // a[3] returns the equivalent of "b", an int[10], and this decays into a pointer to its first element, just like "b"
int val = *p; // Equals 155
最后,就像FredOverflow提到的那样,这也是如此:
int (*p)[10] = a;
语法需要习惯,但它很有意义。由于每个数组名称都会衰减为指向其第一个元素的指针,因此“a”会衰减为指向其第一个元素的指针。这个元素是什么?那么,“a”的每个元素是10个整数的数组,即“int [10]”,所以“a”必须衰减成指向这些“int [10]”元素中的第一个的指针。上面的语法就是你如何声明这个指针。它将“p”定义为指向10个整数数组的指针。由于C ++优先级规则,(圆形)括号是必需的。如果你删除它们,你会得到这个:
int *p[10] = a; // Compiler error!
将“p”声明为10个元素的数组,其中每个元素都是指向int的指针。它不是同一个IOW所以括号需要改变优先级(因此这个声明的含义)。使用前面显示的正确语法,“p”因此将指向第一个元素(包含元素5到50的“int [10]”数组),p + 1将指向第二个元素(“int [10] “包含元素55到100的数组”等。加分点:以下将做什么?
(*(p + 3))[5]
它返回180,因为(p + 3)返回指向“a [3]”的10个整数数组的指针,当使用*运算符取消引用时,在这个位置得到实际的“int [10]”数组。然后[5]下标在此数组中产生值180。
毫无疑问,要解决这个问题仍需要大量的练习,但我希望有所帮助。
答案 4 :(得分:0)
2D C数组不是指向指针的指针。 IT实际上是一个带有行*列元素的指针。
int main(){
int a[10][10];
int *ptr =(int *)a;
cout<<a<<endl<<ptr<<endl;
cout<<*a<<endl<<*ptr<<endl;
return 0;
}
以上内容将为您提供所需信息。
虽然当你取消引用某个或某个ptr时,你会发现你得到一个“未定义的值”
如果你设置[4] [4]来说5
然后你会发现存储在
的值ptr [(row * 10)+ column)将返回row = 4和column = 4的值。