我正在研究的小 c + + 和我在抵制用指针。我知道,我可以通过声明有 3 层的指针︰

int *(*x)[5];

因此, *x是指向的 5 个要素是指向int的指针数组的指针。我还知道, x[0] = *(x+0);x[1] = *(x+1)等等...

那么,为什么已知上面的声明中,是x[0] != x[0][0] != x[0][0][0] ?

2015-07-05 14:28:41
问题评论:

x[0]x[0][0]x[0][0][0]具有不同的类型。它们不能进行比较。通过您意味着什么!= ?

它们是不相同的 @celticminstrel: int **x[5]数组组成的 5 个要素。元素是指向 int 的指针的指针

@celticminstrel int** x[5]将是五指向 int. int *(*x)[5]是五指向整数的指针数组的指针的指针所指向的指针数组

@celticminstrel从右左规则spirale 规则C 杂乱 ↔ 英语和方式成为三星级程序员 :)

@Leo91︰ 首先,您有个指针在这里,没有三个级别。其次,做x[0] != x[0][0] != x[0][0][0]意味着?这不是 c + + 中有效的比较。即使拆分为x[0] != x[0][0]x[0][0] != x[0][0][0]它是仍然无效。因此,您的问题意味着什么?

回答:

x是一个指针,指向 5 指向int的指针数组.
5 指向int的指针x[0]是一个数组.
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]包含一个int0x100的地址.
  • x[0][0][0]包含10的一个int.

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

此图是我有点困惑︰ 0x100应紧靠左边的框中包含10,相同方式, 0x500将显示其框的左侧。而不是它正在远向左,和更低。

@MattMcNabb我不认为它应该是令人费解,但根据您为更高的清晰度的建议更改。

@haccks-我今天非常高兴:)该关系图很好的原因是因为您甚至不需要您赋予它后面的解释。该关系图本身是很容易理解它已回答的问题。后面的文本是只是奖金。

您还可以使用 yed,图表的软件。它将帮助我很多整理我的想法的

@rpax AsciFlow还好

x[0] != x[0][0] != x[0][0][0]
是的根据您自己的帖子
*(x+0) != *(*(x+0)+0) != *(*(*(x+0)+0)+0)
这简化了
*x != **x != ***x

它为什么应该相等?
第一个是一些指针的地址。
第二个是另一个指针的地址。
而第三个是有些int值。

我弄不懂...如果 x [0]、 [0] [0] x [0] [0] [0] 等同于 * (x + 0),* (x + 0 + 0),* (x + 0 + 0 + 0),为什么他们应该有不同的地址吗?

@Leo91 x[0][0](x[0])[0],即*((*(x+0))+0)、 不*(x+0+0)取消引用之前第二个[0].

@Leo91 x[0][0] != *(x+0+0)就像x[2][3] != x[3][2].

@Leo91,"答对了现在"的第二个注释已删除。您不了解某些内容 (这可以在应答中更好地解释),或者这不是您这样做?(一些人喜欢不带多信息性内容的注释中删除)

@deviantfan 很抱歉我不能理解您的意思。我知道答案一样帮助 meto 的也很多评论阐明这一概念。

以下是鼠标指针的内存布局︰

   +------------------+
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]会产生"一些整数"。

我相信,它应该是很明显现在,它们是所有不同的原因。


以上是关闭的基本理解,这是为什么我当初我编写了它的方式。但是,如 haccks 正确地指出,第一行不是 100%准确。因此这里有所有细节︰

在 C 语言的定义中, x[0]的值是整数指针整个数组。但是,数组是不能真正执行任何与 C 中的内容您始终可以操作它们的地址或其元素,永远不会作为一个整体的整个数组︰

  1. sizeof运算符,您可以传递x[0]但是,不是真正的值,其结果取决于类型只。

  2. 您可以获取其地址产生x,i.e."地址的数组"与类型int*(*)[5]的值。换句话说︰ &x[0] <=> &*(x + 0) <=> (x + 0) <=> x

  3. 其他所有上下文中,将插入到数组中的第一个元素的指针 decay x[0]的值。就是用"数组的地址"的值和类型int**的指针。效果是相同的一样必须强制转换x为类型int**的指针.

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

x[0]不是数组的地址。

@haccks 是,后面的字母的标准, x[0]不是数组的地址,它是数组本身。我已经添加了深入阐释,以及为什么我编写该x[0]是数组的"地址"。我希望您能喜欢。

  • x[0]取消外面的指针 (指向数组的大小为 5 指向 int 的指针的指针) 的引用并导致大小 5 指向int的指针的数组;
  • x[0][0]取消引用的最外层的指针索引数组,导致指向int的指针;
  • x[0][0][0]取消引用一切得出的具体值。

顺便说一句,如果以往任何时候都感到困惑不解的声明意味着,使用cdecl这些种类.

让考虑逐步表达式x[0]x[0][0]x[0][0][0].

按以下方式定义了x

int *(*x)[5];

表达式x[0]是一个类型的数组,然后int *[5]考虑到该表达式x[0]等效于表达式*x就是我们取消引用指向数组的指针获取数组本身。让它表示像是我们必须声明的 y

int * y[5];

表达式x[0][0]等于y[0] ,而且具有类型int *让它表示像是我们必须声明的 z

int *z;

表达式x[0][0][0]相当于又等于表达式z[0]并且具有类型为int的表达式y[0][0].

所以,我们有

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;
内容来源于Stack Overflow Why is x[0] != x[0][0] != x[0][0][0]?
请输入您的翻译

Why is x[0] != x[0][0] != x[0][0][0]?

确认取消