Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/arrays/12.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
为什么x[0]!=x[0][0]!=x[0][0][0]? 我正在学习一点C++,我在和指针打交道。我明白,通过声明,我可以拥有3级指针: int *(*x)[5];_C++_Arrays_Pointers - Fatal编程技术网

为什么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]
的地址不同

  • x[0]
    取消对最外层指针(指向int的指针大小为5的数组的指针)的引用,并生成指向int的指针大小为5的数组
  • 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::cout
x
是指向
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
    }