【问题标题】:Why is the same value output for A[0], &A, and *A?为什么 A[0]、&A 和 *A 的输出值相同?
【发布时间】:2013-07-12 20:32:28
【问题描述】:

我正在做一个小实验。

#include<cstdio>
#include<iostream>
using namespace std;
int main()
{

  int A[5][5];
  cout<<A[0]<<"  "<<&A<<"   "<<*A;
  return 0;
}

它为所有情况打印相同的值。有人能解释一下为什么会这样吗?

【问题讨论】:

  • 您希望它打印什么?
  • 这已经被问过了。 A[0] 是第一个元素,它衰减成要打印的指针,&amp;A 是地址,它的作用相同,是相同的地址,*A 与第一个相同,真的。
  • 所以A[0]显示的是A[0][0]的地址?
  • It doesn't print the same value in all compilers. 也许这是这里更有趣的问题?
  • @chris 如果它是重复的,也许它应该被关闭为一个

标签: c++


【解决方案1】:

首先要了解的是您要打印的内容:

 cout<<A[0]<<"  "<<&A<<"   "<<*A;

表达式A[0] 是一个左值表达式,类型为int[5],指的是A 中的第一个内部数组,&amp;A 是一个类型为int (*)[5][5] 的右值表达式,它指向数组A。最后*A等价于A[0],即int[5]类型的左值表达式。

语言中没有定义(您也不能提供它们)将转储int[5]int (*)[5][5] 的运算符,因此编译器会尝试找到它可以匹配的最佳并发现有一个运算符打印void*int[5] 可以衰减为引用A[0][0]int*,并且它本身可以转换为void*int (*)[5][5] 是一个指针,因此可以转换为 void*,因此重载对这两种情况都有效。

语言定义了数组在内存中的布局,特别是它要求数组和数组的第一个元素布局在同一个内存地址中,所以如果你要打印&amp;A的地址和&amp;A[0] 将打印相同的值,并且因为&amp;A[0] 也在其第一个元素的相同内存位置,&amp;A[0][0] 也引用相同的地址。

回到上面你正在打印的代码是:

cout<<         static_cast<void*>(&A[0][0]) 
    << "  " << static_cast<void*>(&A)
    << "  " << static_cast<void*>(&A[0][0]);

根据上面的推理,它必须具有相同的精确值,即使在第二种情况下类型不同。

【讨论】:

    【解决方案2】:

    A[0]&amp;A*A 都是指向同一个内存位置的不同类型的指针。相同的值(某种),不同的类型。

    Expression    Symmetric                                          Type  
    ----------------------------------------------------------------------------
    A           address of first row.                               int[5][5]
    &A[0][0]    address of first element                            int* 
    &A          address of 2d array                                 int(*)[5][5]   
    *A         = *( A + 0) = A[0] = address of first element        int[5] = decays to int*
                                                                             in a expression
    

    我的 5*4 维 char 数组示例:

                          A
                        +---201---202---203---204---206--+
        201             | +-----+-----+-----+-----+-----+|   
        A[0] = *(A + 0)--►| 'f' | 'o' | 'r' | 'g' | 's' ||
        207             | +-----+-----+-----+-----+-----+|
        A[1] = *(A + 1)--►| 'd' | 'o' | '\0'| '\0'| '\0'||
        213             | +-----+-----+-----+-----+-----+|
        A[2] = *(A + 2)--►| 'n' | 'o' | 't' | '\0'| '\0'||
        219             | +-----+-----+-----+-----+-----+|
        A[3] = *(A + 3)--►| 'd' | 'i' | 'e' | '\0'| '\0'||
                        | +-----+-----+-----+-----+-----+|
                        +--------------------------------+
    

    关于图形示例的简要说明。

    • 图中A表示从地址201开始的完整二维数组,
    • &amp;A 给出完整二维数组的地址 = 201
    • *A = *(A + 0) = A[0] 指向第一行 = 201
    • 注意值A[0][0] 在我的示例中为'f'&amp;A[0][0] 给出地址为[0][0] element = 201
    • 注意&amp;A[0][0]*A 相同,因为&amp;A[0][0] => &amp;(*(*A)) => &amp;**A => *A

    所以所有A[0]&amp;A*AA 都相同但对称不同。

    观察A[0]&amp;A*AA之间的差异。键入以打印sizeof() 信息。例如

     cout<<sizeof(A[0]) <<" "<<sizeof(&A) <<" "<<sizeof(*A) <<" "<< sizeof(A); 
    

    第二次尝试打印下一个位置地址:

     cout<<(A[0] + 1)<<" "<<(&A + 1) <<" "<<(*A + 1)<<" "<<(A + 1);
    

    更详细的解释,必看answer

    【讨论】:

    • 是的,我不知道为什么这个问题有一个 [c] 标签。 C中没有std::cout
    • 这不是 C 题。 C中没有std::cout
    • @GrijeshChauhan,谈论团队合作者:) 什么是锻造? :p
    【解决方案3】:

    A[0] 这等价于 *(A + 0),或更简单地说是 *A。

    &A 有点棘手。 A 是 int[5][5] 类型,由堆栈上 100 字节的连续区域表示。 A 的地址是该区域的开始 - 它等于指向第一个元素的指针。第一个元素地址也是*A的存储位置。

    【讨论】:

    • 你怎么知道它是 100 字节?
    • 来吧...不是标准的,但 sizeof(int) == 4 在所有非 DSP、非嵌入式平台中存在。更有用的是那些 cmets 将是在线的东西:你假设一个架构,sizeof(int)==4。顺便说一句,挪威,你假设 32 位整数!
    【解决方案4】:

    数组,在最基本的层面上,是指向内存中某个位置的指针。数组中的其他元素连续存储在该元素之后,并且索引告诉计算机从第一个元素跳转到所需的位置的位置。 A[0]是打印第一行第一个元素的地址,&amp;A是打印A所在的地址,也就是第一行第一个元素的位置,*A同为A[0]

    【讨论】:

      猜你喜欢
      • 2013-08-24
      • 1970-01-01
      • 1970-01-01
      • 2019-03-07
      • 2017-05-19
      • 2017-03-12
      • 1970-01-01
      • 1970-01-01
      • 2015-09-14
      相关资源
      最近更新 更多