arr和* arr有什么区别?

时间:2019-04-16 17:50:57

标签: c arrays pointers

这两张照片之间有什么区别,我在两张照片中都有相同的地址:

int main(void)
{
    int arr[2][3] = {{1,2,3},{4,5,6}};
    printf("%p\n", arr);
    printf("%p\n", *(arr));
}

3 个答案:

答案 0 :(得分:1)

arr是3 int的2个数组的数组。考虑以下三件事:

  • 数组arr
  • arr的第一个子数组,也称为arr[0]
  • arr[0]的第一个元素,也称为arr[0][0]

这三件事始于同一个地方。 arr中的第一个子数组位于arr的开头,因此它从arr开始的地方开始。 arr[0]的第一个元素在arr[0]的开头,并且在arr的开头。由于这三件事都是从同一地方开始的,因此它们看上去在同一地址也就不足为奇了。

现在,让我们看看您打印的内容。首先,在打印指针时,应将其转换为void *,就像在printf("%p\n", (void *) arr);中一样。

也就是说,printf(… arr)打印arr[0]的地址。为什么选择arr[0]而不选择arr?因为在这样的表达式中使用数组时,数组会自动转换为指向其第一个元素的指针。因此arr会自动转换为指向arr[0]的指针,这就是printf打印的内容。

类似地,printf(… *(arr))打印arr[0][0]的地址。这是因为,如上所述,arr被转换为指向arr[0]的指针。然后,由于它是指向arr[0]的指针,因此*(arr)*应用于该指针,结果为arr[0]。由于arr[0]是一个数组,因此它也将转换为指向其第一个元素的指针。因此,结果是指向arr[0][0]的指针,这就是printf打印的内容。

因此,您正在打印arr[0]的地址和arr[0][0]的地址。由于它们始于同一位置,因此地址相同也就不足为奇了。

(实际上并不需要打印地址会产生相同的字符串。C标准允许实现以多种方式表示地址。因此,打印指向同一地址的两个不同的指针可能会导致不同的输出在现代C语言实现中相当罕见。)

答案 1 :(得分:1)

除非它是sizeof或一元&运算符的操作数,或者是用于在声明中初始化字符数组的字符串文字,否则为 expression 类型为“ T的N元素数组”的表达式将转换为“指向T的指针的表达式(“衰减”),该表达式的值是的第一个元素的地址数组。

给出声明

int arr[2][3] = {{1, 2, 3}, {4, 5, 6}};

内存布局将

   +---+
a: | 1 | a[0][0]
   +---+ 
   | 2 | a[0][1]
   +---+
   | 3 | a[0][2]
   +---+
   | 4 | a[1][0]
   +---+
   | 5 | a[1][1]
   +---+
   | 6 | a[1][2]
   +---+

因此,需要注意的一件事-a的地址将与a[0]的地址相同,而该地址也将与a[0][0]的地址相同。 a[1]的地址将与a[1][0]的地址相同。

表达式 a的类型为“ int的3元素数组的2元素数组”,因此,除非它是&或{ {1}},表达式的类型将“衰减”为“指向sizeofint)的3元素数组的指针,其值将是{{ 1}}(int (*)[3])。

表达式a的类型为“ &a[0]的3元素数组,因此,除非它是*aint的操作数,否则表达式的类型将为从“衰减”到“指向&的指针,表达式的值将是sizeofint的第一元素的地址,它等效于*a)。

如上所述,&(*a)[0]的地址与&a[0][0]的地址相同,也与a的地址相同。实际上,以下所有 表达式的求值地址都相同:a[0]a[0][0]&aa*aa[0],尽管表达式的类型不同。参见下表:

&a[0]

答案 2 :(得分:0)

没有索引的arr基本上是指向数组的zeroeth元素的指针,在您的问题中没有区别

arr <==> *arr

这就是您获得相同地址的原因,在下一阶段中,我们要访问数组元素,然后一个方法很简单arr[i][j]或您可以使用指针{{1 }},现在的实现似乎彼此之间有更多不同,但是就像您的情况一样,它们都访问相同的地址,因此在此示例中,该地址也将相同,并且在所有这种情况下都相同。