【问题标题】:What is the difference between `a` and `*a` where `a` denotes a 2D array?`a` 和 `*a` 有什么区别,其中 `a` 表示二维数组?
【发布时间】:2015-08-16 01:32:13
【问题描述】:

指针和数组是紧密联系在一起的,所以,如果我们有一个二维数组

int a[3][4]={
             1,2,3,4,
             5,6,7,8,
             9,10,11,12};

两个

printf("%p\n", a);

printf("%p\n", *a);

打印相同的地址。我的理解可能是a指向a的基地址,而*a指向二维数组a的第一个子数组。

那么,这两者有什么区别呢?

【问题讨论】:

  • 当我们需要访问数组 rt 的不同元素时,可能会出现差异?
  • 比较 sizeof(a)sizeof(*a)

标签: c arrays pointers multidimensional-array syntax


【解决方案1】:

我得到的可能是 a 指向了一段时间的基地址 *a 是指向二维数组a的第一个子数组。

差不多了。

  • 当您将a 传递给printf 时,a 会自行衰减为指向其第一个子数组的指针(int(*)[3] 类型)。
  • *a 指定a 的第一个子数组(int[3] 类型),并衰减为指向该子数组第一个元素的指针(int* 类型)。

最后,它们共享相同的值,因为数组具有与其第一个元素相同的地址,递归。

【讨论】:

  • 当您将它传递给 printf 时,a 会自行衰减为指向其第一个子数组的指针 ?我没有得到这个
  • 问题是“它们有什么区别?”而不是“a*a如何指向同一个位置?” .
  • @RohitSaluja 数组名称(例如 a)在除少数上下文之外的所有上下文中衰减为指向其第一个元素的指针。函数调用参数是一个衰减的上下文。
  • @CoolGuy a*a 的两个子弹比较怎么回答不了问题?
  • 对我来说,这两个项目符号说的是同一件事,但方式不同。您已经解释了相似之处而不是不同之处。
【解决方案2】:

指针(数组衰减到的)之间的区别不是地址而是类型。

如您所见,两个指针都指向同一个地址。但是a 指向子数组,而*a 指向ints。

这会有所不同,例如在进行地址运算时。 a + 1*a + 1 不同。

【讨论】:

  • 我只是想知道类型。所以,aint(*)[3] 类型,*aint*,对吧?
  • @CoolGuy ...腐烂后 ;)
  • a 是 int()[3] 类型并且 *a 是 int 所以 a 是一个指向数组的指针,就像我们有指向整数的指针?如果是这样,为什么我们需要使用指向数组的指针?
【解决方案3】:

这很简单。 *a 是一个整数数组。在你的情况下*a 只是数组[1,2,3,4]。此数组的各个元素可以通过(*a)[i] 访问,其中i 是所需元素的索引。

a 是指向这个整数数组的指针。 a[0] 会给你第一个数组(它与*a 相同),a[1] 会给你第二个数组(它是[5,6,7,8])。

例如,如果您想访问第 5 个元素(即5),它将是a[1][0]

【讨论】:

    【解决方案4】:

    a 是一个 3x4 大小的二维数组。这意味着:

    • sizeof(a) == 3*4*sizeof(int)
    • a[i] 是一个大小为 4 的一维数组(对于 0
    • a[i][j] 是一个 int ( 0
    • 当用作指针时a 衰减为&a[0]

    *aa[0]:它是一个大小为 4 的一维数组。这意味着:

    • sizeof(*a) == 4*sizeof(int)
    • (*a)[i] 是一个 int (0
    • 当用作指针时*a 衰减为&a[0][0]

    所以a*a 是不同的对象,它们会衰减到指向同一地址的指针,该地址也是&a。但是a 衰减为指向int[4] 的指针,而*a 衰减为指向int 的指针(感谢 undur_gongor 的注意)。

    【讨论】:

    • 最后一句不清楚。你能检查一下语法吗?
    • "它本身会衰减为 &a[0][0]" -- 你确定吗?这意味着a + 1*a + 1 是相同的。他们不是。
    【解决方案5】:

    鉴于声明

    int a[3][4];
    

    以下是正确的:

    Expression     Type            Decays to        Value
    ----------     ----            ---------        -----
             a     int [3][4]      int (*)[4]       Base address of array
            &a     int (*)[3][4]   n/a              Base address of array
            *a     int [4]         int *            Base address of first subarray
                                                    (equivalent to a[0])
          a[i]     int [4]         int *            Base address of i'th subarray
         &a[i]     int (*)[4]      n/a              Base address of i'th subarray
         *a[i]     int             n/a              Value of a[i][0]
       a[i][j]     int             n/a              Value of a[i][j]
      &a[i][j]     int *           n/a              Address of a[i][j]
    

    数组的第一个元素的地址与数组本身的地址相同,所以表达式a&a*aa[0]&a[0]&a[0][0]都产生相同的(数组的第一个元素的地址),但它们会有不同的类型int (*)[3][4] vs. int (*)[4] vs. @987654332 @)。

    编辑

    除非它是sizeof 或一元& 运算符的操作数,否则将转换类型为“T 的N 元素数组”的表达式(“衰减”)到“指向T”类型的表达式,表达式的值将是数组第一个元素的地址。

    所以表达式*a等价于a[0];这两个表达式的类型都是“int 的 4 元素数组”。由于它们不是sizeof 或一元& 运算符的操作数,因此这些表达式“衰减”为“指向int 的指针”。

    这就是“衰减到”列所显示的内容。

    请参阅online C 2011 language standard 的第 6.3.2.1 节。

    【讨论】:

    • 我们如何才能看到这里的指针类型?
    • @RohitSaluja:对于数组,它位于“衰减到”列中。对于指针,它位于“类型”列中。
    • 好吧,我明白了,虽然它们指向同一个地址,但它们是不同的,但是在上述类型中,我只能得到 *a 类型,它是 int[4],所以它是像指向数组的指针,但我无法了解其他类型的行为方式?能否请您提供与指针和多维数组相关的源材料,以便我很好地理解它
    • @John 好吧,感谢您的来源,但我不习惯理解这些标准文档。如果你能用更简单的语言解释会很有帮助:)
    • @RohitSaluja:这很简单。当aint 的 3x4 数组)或*aint 的 4 元素数组)之类的数组表达式出现在您的代码中时,它们将被替换为指针表达式,其值为第一个元素,除非表达式是 sizeof 或一元 & 运算符的操作数。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-06-27
    • 1970-01-01
    • 1970-01-01
    • 2021-09-17
    • 2019-01-12
    • 2012-07-03
    • 1970-01-01
    相关资源
    最近更新 更多