为什么x [0]!= x [0] [0]!= x [0] [0] [0]?

Leo*_*o91 148 c c++ arrays pointers

我正在研究一些C++,我正在用指针进行斗争.我明白通过声明我可以有3个级别的指针:

int *(*x)[5];
Run Code Online (Sandbox Code Playgroud)

所以这*x是一个指向5个指向的元素数组的指针int.我也知道x[0] = *(x+0);,x[1] = *(x+1)等等....

那么,鉴于上述声明,为什么x[0] != x[0][0] != x[0][0][0]呢?

hac*_*cks 258

x是一个指向5个指针数组的指针int.
x[0]是一个 5指针的数组int.
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                    
                     |      |                                             
                     +------+                                             
Run Code Online (Sandbox Code Playgroud)

你可以看到

  • x[0]是一个数组,当在表达式中使用时将转换为指向其第一个元素的指针(有一些例外).因此x[0]将给出其第一元素的地址x[0][0]0x500.
  • x[0][0]包含的地址int0x100.
  • x[0][0][0]包含int10.

所以,x[0]等于&x[0][0],因此,&x[0][0] != x[0][0].
因此,x[0] != x[0][0] != x[0][0][0].

  • @haccks - 我很高兴:)这个图表很棒的原因是因为你甚至不需要你所遵循的解释.该图本身是不言自明的,它已经回答了这个问题.接下来的文字只是一个奖励. (4认同)

dev*_*fan 133

x[0] != x[0][0] != x[0][0][0]
Run Code Online (Sandbox Code Playgroud)

是,根据你自己的帖子,

*(x+0) != *(*(x+0)+0) != *(*(*(x+0)+0)+0)`  
Run Code Online (Sandbox Code Playgroud)

这是简化的

*x != **x != ***x
Run Code Online (Sandbox Code Playgroud)

它为什么要平等?
第一个是某个指针的地址.
第二个是另一个指针的地址.
第三个是一些int价值.

  • @ Leo91`x [0] [0]`是`(x [0])[0]`,即`*((*(x + 0))+ 0)`,而不是`*(x + 0 + 0 )`.取消引用发生在第二个"[0]"之前. (41认同)
  • @ Leo91`x [0] [0]!=*(x + 0 + 0)`就像`x [2] [3]!= x [3] [2]`. (4认同)

cma*_*ter 49

这是指针的内存布局:

   +------------------+
x: | address of array |
   +------------------+
            |
            V
            +-----------+-----------+-----------+-----------+-----------+
            | pointer 0 | pointer 1 | pointer 2 | pointer 3 | pointer 4 |
            +-----------+-----------+-----------+-----------+-----------+
                  |
                  V
                  +--------------+
                  | some integer |
                  +--------------+
Run Code Online (Sandbox Code Playgroud)

x[0]产生"数组的地址",
x[0][0]产生"指针0",
x[0][0][0]产生"某个整数".

我相信,现在应该是显而易见的,为什么它们都是不同的.


上面的内容足够基本的理解,这就是我写它的方式.然而,正如haccks正确指出的那样,第一行不是100%精确.所以这里有所有细节:

从C语言的定义来看,值x[0]是整个整数指针数组.但是,数组是你在C中无法做任何事情的东西.你总是操纵它们的地址或它们的元素,而不是整个数组:

  1. 您可以传递x[0]sizeof运营商.但这并不是对价值的实际使用,其结果仅取决于类型.

  2. 您可以使用其产生值的x地址,即具有类型的"数组地址" int*(*)[5].换一种说法:&x[0] <=> &*(x + 0) <=> (x + 0) <=> x

  3. 所有其他上下文中,值x[0]将衰减为指向数组中第一个元素的指针.也就是说,一个具有值"数组的地址"和类型的指针int**.效果与转换为x类型指针的效果相同int**.

由于在情况3中的数组指针衰减,所有的使用x[0]最终导致指向指针数组的开始的指针; 该调用printf("%p", x[0])将打印标记为"数组地址"的存储单元的内容.


d12*_*25q 18

  • x[0]取消引用最外面的指针(指向 int的指针大小为5的数组的指针),并得到一个指向大小为5的数组int;
  • x[0][0]取消引用最外面的指针索引数组,从而得到一个指针int;
  • x[0][0][0] 取消引用所有内容,从而产生具体价值.

顺便说一句,如果您对这些声明的含义感到困惑,请使用cdecl.


Vla*_*cow 11

让我们考虑一步一步的表达x[0],x[0][0]x[0][0][0].

由于x被定义如下方式

int *(*x)[5];
Run Code Online (Sandbox Code Playgroud)

那么expression x[0]是一个类型的数组int *[5].考虑到表达式x[0]等同于表达式*x.这是取消引用指向数组的指针,我们得到数组本身.让我们像y一样表示我们有一个声明

int * y[5];
Run Code Online (Sandbox Code Playgroud)

表达式x[0][0]相当于y[0]并且具有类型int *.让我们像z一样表示我们有一个声明

int *z;
Run Code Online (Sandbox Code Playgroud)

表达式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;
Run Code Online (Sandbox Code Playgroud)


apm*_*apm 10

首先我要说的是

x [0] =*(x + 0)=*x;

x [0] [0] =*(*(x + 0)+ 0)=**x;

x [0] [0] [0] =*(*(*(x + 0)+ 0))=***x;

所以*x≠**x≠***x

从下图中可以看出所有事情都很清楚.

  x[0][0][0]= 2000

  x[0][0]   = 1001

  x[0]      = 10
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述

这只是一个例子,其中x [0] [0] [0]的值= 10

并且x [0] [0] [0]的地址1001

该地址存储在x [0] [0] = 1001中

并且x [0] [0]的地址2000

并且该地址存储在x [0] = 2000

所以x [0] [0] [0] x [0] [0] x [0]

.

编辑位点

计划1:

{
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);
}
Run Code Online (Sandbox Code Playgroud)

产量

142041096 142041112 142041128 10
10 142041128 142041112 142041096 -1076392836
Run Code Online (Sandbox Code Playgroud)

计划2:

{
int x[1][1][1]={10};
printf("%d   %d   %d   %d \n ",x[0][0][0],x[0][0],x[0],&x);
}
Run Code Online (Sandbox Code Playgroud)

产量

10   -1074058436   -1074058436   -1074058436 
Run Code Online (Sandbox Code Playgroud)

  • 你的回答是误导性的.`x [0]`不包含ant地址.它是一个阵列.它将衰减指向其第一个元素. (3认同)

小智 7

如果您要从真实世界的角度查看数组,它将如下所示:

x[0]是一个装满板条箱的货运集装箱.
x[0][0]在货运集装箱内是一个装满鞋盒的单箱.
x[0][0][0]是货箱内的单个鞋盒,在货柜内.

即使它是货运集装箱中唯一的箱子里唯一的鞋盒,它仍然是鞋盒而不是货运集装箱