C语言二维数组的名称的困惑?

#include <stdio.h>

int main() {

int arr[10][10] = {0};

printf("arr is %p\n", arr);

printf("*arr is %p\n", *arr);

printf("&arr[0][0] is %p\n", &arr[0][0]);

return 0;

}

输出的结果为:

arr is 0x7fffedc99d40

*arr is 0x7fffedc99d40

&arr[0][0] is 0x7fffedc99d40

这里有个困惑,如果arr和*arr值是一样的,那是不是就意味着这样一个事实:arr内存放着一个地址0x7fffedc99d40,我通过*arr的方式去寻找0x7fffedc99d40这个地址对应的存储区,把里面的东西取出来,发现0x7fffedc99d40这个存储区里放的也是个地址,地址是0x7fffedc99d40,那如果我再做一次寻址,即**arr,我找到的还是存储区0x7fffedc99d40,它里面放的也是地址0x7fffedc99d40,但实际上**arr对应的存储区放的应该是值。

现在问题是,0x7fffedc99d40这个存储区里到底放的应该是什么?

 arr内存放着一个地址0x7fffedc99d40
不是放着地址,而是arr其实就是这个地址。
这是编译器的魔术(语法糖)。
所以
char str[100];
scanf("%s", str);
按理说,scanf需要一个地址参数,但是写str也可以,和&str[0]一样。

怎么最近好多问指针的。

0x7fffedc99d40存放的就是arr的第一个元素arr[0][0]

arr这个二维数组的起始地址和arr[0]这个一维数组的起始地址是一样的,都是0x7fffedc99d40

这里面有一个左值右值的概念,此处的arr是二维数组,arr表示的是数组名,它是个左值,直接打印它会是这个二维数组第一个元素所在地址,同理*arr 实质上是一维数据的数组名,也是个左值,直接打印它会是这个一维数组第一个元素所在地址。如果是**arr,他就是右值,那即第一个元素的地址空间内存放的元素值。

推荐你一本书,c和指针