为什么x[0]!=x[0][0]!=x[0][0][0]? 我正在学习一点C++,我在和指针打交道。我明白,通过声明,我可以拥有3级指针: int *(*x)[5];
因此,为什么x[0]!=x[0][0]!=x[0][0][0]? 我正在学习一点C++,我在和指针打交道。我明白,通过声明,我可以拥有3级指针: int *(*x)[5];,c++,arrays,pointers,C++,Arrays,Pointers,因此,*x是指向5个元素的数组的指针,这些元素是指向int的指针。 我也知道x[0]=*(x+0),x[1]=*(x+1)等等 那么,鉴于上述声明,为什么x[0]!=x[0][0]!=x[0][0][0] x[0] != x[0][0] != x[0][0][0] 根据你自己的帖子 *(x+0) != *(*(x+0)+0) != *(*(*(x+0)+0)+0)` 这是简化的 *x != **x != ***x 为什么它应该是相等的? 第一个是某个指针的地址。 第二个是另一个指针的地
*x
是指向5个元素的数组的指针,这些元素是指向int
的指针。
我也知道x[0]=*(x+0)
,x[1]=*(x+1)
等等
那么,鉴于上述声明,为什么x[0]!=x[0][0]!=x[0][0][0]
x[0] != x[0][0] != x[0][0][0]
根据你自己的帖子
*(x+0) != *(*(x+0)+0) != *(*(*(x+0)+0)+0)`
这是简化的
*x != **x != ***x
为什么它应该是相等的?第一个是某个指针的地址。
第二个是另一个指针的地址。
第三个是一些
int
值。您试图通过值来比较不同的类型
如果你接受这些地址,你可能会得到更多你想要的
请记住,你的声明会带来不同
int y [5][5][5];
将允许您进行所需的比较,因为y
,y[0]
,y[0][0]
,y[0][0]
将具有不同的值和类型,但地址相同
int **x[5];
不占用相邻的空间
x
和x[0]
的地址相同,但x[0][0]
和x[0][0]
的地址不同
取消对最外层指针(指向int的指针大小为5的数组的指针)的引用,并生成指向int的指针大小为5的数组李>x[0]
取消对最外层指针的引用并对数组进行索引,从而生成指向x[0][0]
的指针李>int
取消对所有内容的引用,从而生成一个具体的值x[0][0][0]
顺便说一下,如果你对这些声明的含义感到困惑,请使用.< /P> < P>让我们考虑一步一步的表达式<代码> x [ 0 ] <代码>,<代码> x [ 0 ] [ 0 ] <代码>和<代码> x [ 0 ] [ 0 ] [0 ] < /代码> ./p> As
x
的定义如下
int *(*x)[5];
表达式
x[0]
是int*[5]
类型的数组。考虑到表达式x[0]
等同于表达式*x
。这就是取消对数组指针的引用,我们得到了数组本身。让我们用y来表示,我们有一个声明
int * y[5];
int *z;
表达式x[0][0]
相当于y[0]
,类型为int*
。让我们用z来表示,我们有一个声明
int * y[5];
int *z;
表达式x[0][0][0]
等价于表达式y[0][0]
,该表达式反过来等价于表达式z[0]
,并具有类型int
所以我们有
x[0]
具有类型int*[5]
x[0][0]
具有类型int*
x[0][0][0]
具有类型int
因此,它们是不同类型、不同大小的对象
比如说跑步
std::cout << sizeof( x[0] ) << std::endl;
std::cout << sizeof( x[0][0] ) << std::endl;
std::cout << sizeof( x[0][0][0] ) << std::endl;
std::coutx
是指向int
的5个指针数组的指针
x[0]
是指向int
的5个指针数组
x[0][0]
是指向int
的指针
x[0][0][0]
是一个int
x[0]
Pointer to array +------+ x[0][0][0]
x -----------------> | | Pointer to int +-------+
0x500 | 0x100| x[0][0]----------------> 0x100 | 10 |
x is a pointer to | | +-------+
an array of 5 +------+
pointers to int | | Pointer to int
0x504 | 0x222| x[0][1]----------------> 0x222
| |
+------+
| | Pointer to int
0x508 | 0x001| x[0][2]----------------> 0x001
| |
+------+
| | Pointer to int
0x50C | 0x123| x[0][3]----------------> 0x123
| |
+------+
| | Pointer to int
0x510 | 0x000| x[0][4]----------------> 0x000
| |
+------+
你可以看到
x[0]
是一个数组,在表达式中使用时将转换为指向其第一个元素的指针(有些例外)。因此x[0]
将给出其第一个元素x[0][0]
的地址,即0x500
李>
x[0][0]
包含int
的地址,即0x100
李>
x[0][0][0]
包含int
值10
李>
因此,x[0]
等于&x[0][0]
,因此,&x[0][0]!=x[0][0]
因此,x[0]!=x[0][0]!=x[0][0][0]
以下是指针的内存布局:
+------------------+
x: | address of array |
+------------------+
|
V
+-----------+-----------+-----------+-----------+-----------+
| pointer 0 | pointer 1 | pointer 2 | pointer 3 | pointer 4 |
+-----------+-----------+-----------+-----------+-----------+
|
V
+--------------+
| some integer |
+--------------+
x[0]
产生“数组地址”,
x[0][0]
产生“指针0”,
x[0][0][0]
生成“某个整数”
我相信,现在应该很明显,为什么他们都不同了
上面的内容已经足够基本理解了,这就是为什么我用我写的方式来写它。然而,正如哈克斯正确指出的那样,第一行并非100%精确。下面是所有细节:
根据C语言的定义,x[0]
的值是整型指针的整个数组。但是,在C中,数组实际上是无法处理的。您总是操纵它们的地址或元素,而不是整个数组:
您可以将x[0]
传递给sizeof
操作符。但这并不是值的真正用途,它的结果只取决于类型
您可以获取其地址,该地址产生x
,i的值。E类型为int*(*)[5]
的“数组地址”。换句话说:&x[0]&*(x+0)(x+0)x
在所有其他上下文中,x[0]
的值将衰减为指向数组中第一个元素的指针。也就是说,指针的值为“数组地址”,类型为int**
。其效果与将x
强制转换为int**
类型的指针的效果相同
由于案例3中的数组指针衰减,x[0]
的所有使用最终导致指针指向指针数组的开头;调用<代码> PROTF(“%P”,X(0))< /C>将打印被标记为“数组地址”的内存单元的内容。 < P> C++中有一个原则,这样一个变量的声明就可以准确地指示变量的使用方式。考虑你的声明:
int *(*x)[5];
可以改写为(为了更清楚):
基于这一原则,我们有:
*((*x)[i]) is treated as an int value (i = 0..4)
→ (*x)[i] is treated as an int* pointer (i = 0..4)
→ *x is treated as an int** pointer
→ x is treated as an int*** pointer
因此:
x[0] is an int** pointer
→ x[0][0] = (x[0]) [0] is an int* pointer
→ x[0][0][0] = (x[0][0]) [0] is an int value
所以你可以找出区别 首先我要说的是
x[0]=*(x+0)=*x
x[0][0]=*(*(x+0)+0)
{
int ***x;
x=(int***)malloc(sizeof(int***));
*x=(int**)malloc(sizeof(int**));
**x=(int*)malloc(sizeof(int*));
***x=10;
printf("%d %d %d %d\n",x,*x,**x,***x);
printf("%d %d %d %d %d",x[0][0][0],x[0][0],x[0],x,&x);
}
142041096 142041112 142041128 10
10 142041128 142041112 142041096 -1076392836
{
int x[1][1][1]={10};
printf("%d %d %d %d \n ",x[0][0][0],x[0][0],x[0],&x);
}
10 -1074058436 -1074058436 -1074058436
p == &p[0] == &(&p[0])[0] == &(&(&p[0])[0])[0])
p == &*(p+0) == &*(&*(p+0))+0 == &*(&*(&*(p+0))+0)+0
p == p+0 == p+0+0 == p+0+0+0 == (((((p+0)+0)+0)+0)+0)
#include <stdio.h>
int main () {
int *(*x)[5];
x = (int *(*)[5]) &x;
printf("%p\n", x[0]);
printf("%p\n", x[0][0]);
printf("%p\n", x[0][0][0]);
}
$ ./ptrs
0xbfd9198c
0xbfd9198c
0xbfd9198c
0xbfd9198c
+------------+
| 0xbfd9198c |
+------------+
void function (int* x[5][5][5]){
printf("%p",&x[0][0][0][0]); //get the address of the first int pointed to by the 3d array
}
void function (int* (*x)[5][5][5]){
printf("%p",&x[0][0][0][0][0]); //get the address of the first int pointed to by the 3d array
}