你是不是看漏了&号,导致你把 &arr 和 arr 混淆了?
int a;
sizeof(a); // 4bytes (当然不一定是4字节,但这与本话题无关)
printf("%p",&a); // 对应a的地址
printf("%p",&a + 1); // 对应a下一个变量的地址(a下一个变量 可以不存在,但取其地址是良好定义行为,而对 a下一个变量的下一个变量 取值则是未定义行为,即 &a+2 属于未定义行为,当然这与本话题无关)
仿造上面的代码,你应该写出
int arr[] = {1,2,3,4,5};
sizeof(arr); // 4 * 5B
printf("%p",
&arr);
printf("%p",
&arr + 1);
亦即,你提供的证据 与 你的疑问 不构成联系。
而 printf("%p", arr); printf("%p", arr + 1) 之所以合法则是因为C语言规定「数组可以隐式地转化成指针」
亦即 printf("%p", arr); 等同于 printf("%p", &arr[0] );
printf("%p", arr+1); 等同于 printf("%p", &arr[0] + 1 );
假设作为参数传给某个函数形参接收时,sizeof(形参)得到的又是指针的大小,
因为
数组不可拷贝,即
int a[3] = { 0, 1, 2 };
int b[3] = a; 是不合法的!
对于函数 void foo( int a[3] ) 而言,你怎么传参数给它?
所以这是C语言规定「数组可以隐式地转化成指针」的原因,亦即void foo( int a[3] ) 等同于 void foo( int a[4] ) 等同于 void foo( int* a ) 等同于 ……,本质上都是 void foo( int* a )