这两张照片之间有什么区别,我在两张照片中都有相同的地址:
int main(void)
{
int arr[2][3] = {{1,2,3},{4,5,6}};
printf("%p\n", arr);
printf("%p\n", *(arr));
}
答案 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}},表达式的类型将“衰减”为“指向sizeof
(int
)的3元素数组的指针,其值将是{{ 1}}(int (*)[3]
)。
表达式a
的类型为“ &a[0]
的3元素数组,因此,除非它是*a
或int
的操作数,否则表达式的类型将为从“衰减”到“指向&
的指针,表达式的值将是sizeof
(int
的第一元素的地址,它等效于*a
)。
如上所述,&(*a)[0]
的地址与&a[0][0]
的地址相同,也与a
的地址相同。实际上,以下所有 表达式的求值地址都相同:a[0]
,a[0][0]
,&a
,a
,*a
,a[0]
,尽管表达式的类型不同。参见下表:
&a[0]
答案 2 :(得分:0)
没有索引的arr基本上是指向数组的zeroeth元素的指针,在您的问题中没有区别
arr <==> *arr
这就是您获得相同地址的原因,在下一阶段中,我们要访问数组元素,然后一个方法很简单arr[i][j]
或您可以使用指针{{1 }},现在的实现似乎彼此之间有更多不同,但是就像您的情况一样,它们都访问相同的地址,因此在此示例中,该地址也将相同,并且在所有这种情况下都相同。