【问题标题】:(arr + 2) is equivalent to *(arr + 2) . How?(arr + 2) 等价于 *(arr + 2) 。如何?
【发布时间】:2018-08-28 16:40:17
【问题描述】:

我正在研究如何在指针的帮助下显示二维数组的元素。这是我尝试过的代码:

#include<stdio.h>  

int main(){

    int arr[3][2] = {  

    {7, 8},
    {6,3},
    {3,4}
    };

    printf("%u\n", (arr + 2));
    printf("%u\n", *(arr + 2)); 
}

输出:

6487616
6487616

我期望*(arr + 2) 的输出为3。怎么和(arr + 2)一样?

【问题讨论】:

  • 你需要取消引用它两次,因为它是一个二维数组:*(*(arr+2))
  • arr[2]*(arr + 2) 在语言 (C11 §6.5.2.1 Array subscripting ¶2) 中的定义相同。你会得到奇怪的结果,因为你打印的是地址,而不是数组中单元格的值。这是官方未定义的行为;您将地址传递给printf(),但告诉它它有一个无符号整数可以处理。在 32 位平台上,您可能或多或少都可以。结果在 64 位平台上并不可靠。
  • 从技术上讲,您得到的是 UB,因为 %u 不用于打印指针。 You have to use %zu
  • @phuclv:你说得对,%u 是 UB,但使用 %zu 也是如此(用于打印 size_t)。您应该使用%p 并将指针转换为void *,或使用&lt;inttypes.h&gt;PRIuPTR(或PRIXPTR 用于大写十六进制)加上转换为uintptr_t
  • @phuclv:错误。 %zu 需要 size_t 参数。任何不兼容的类型都会触发未定义的行为。指针参数将触发未定义的行为。

标签: c arrays pointers


【解决方案1】:

二维数组实际上是数组的数组。

表达式arr + 2 的类型为int (*)[2],而*(arr + 2) 的类型为int [2]。打印前者时,您有一个指针,以便打印指针的值。在后一种情况下,您有一个数组,它衰减到指向第一个元素的指针。所以*(arr + 2)衰减成arr + 2,和第一个表达式一样。

详细了解arr + 2arr 的类型为int [3][2]。当你给它加上一个整数值时,它会衰减为指向第一个成员的指针,所以arr衰减为int (*)[2]类型,而arr + 2也有该类型,并指向包含{ 3, 4 }的子数组。

还请注意,指针应使用%p 格式说明符打印,并且指针必须强制转换为void *,否则调用undefined behavior。在这种情况下,您“幸运”他们碰巧打印了相同的东西。

要获得您期望的 3 的输出,您需要再取消引用一次:

*(*(arr + 2))

【讨论】:

  • *(*(arr + 2)); 抛出 [Error] expected ')' before ';' token*(*(arr + 1) + 1)); 打印 3
  • @dave *(*(arr + 2)) 适合我。您的printf 调用可能缺少右括号。此外,*(*(arr + 1) + 1)) 正在选择一个不同的数组元素,该元素恰好与您尝试打印的元素具有相同的值。 arr[2][0]arr[1][1] 都包含值 3。
【解决方案2】:

arrint 的数组。在几乎任何用途中,数组都会转换为指向其第一个元素的指针。所以arr 被转换为指向int 数组的指针。

好的,arr 被转换为指向int 数组的指针,因此(arr+2) 属于同一类型,即指向int 数组的指针。

现在*(arr+2)(arr+2) 指向的东西。即int的数组。

现在因为它是一个int 的数组,它被转换为指向其第一个元素的指针。所以*(arr+2) 被转换为指向int 的指针。请注意,它不是int,不太可能等于3

现在(arr+2)*(arr+2) 怎么玩一样?它们是指向数组的指针和指向其第一个元素的指针。虽然这些指针类型不同,但它们代表的是同一个地址,因为任何数组的地址都与其第一个元素的地址相同。

【讨论】:

    【解决方案3】:

    arr 是指向int[2] 类型的第一个数组的指针。(arr + 2) 是指向第三个此类数组的指针。
    *(arr + 2) 是指向(arr +2) 数组的第一个元素的指针。
    因此,它们都将具有相同的地址,因为它们指向相同的位置。唯一的区别在于它们的类型。(arr+2)int(*)[2] 类型,而 *(arr + 2)int * 类型。

    【讨论】:

      猜你喜欢
      • 2017-11-06
      • 2012-12-05
      • 2019-03-21
      • 1970-01-01
      • 2019-12-19
      • 1970-01-01
      • 2015-07-31
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多