指针的介绍2前
1.数组名的理解
#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
int main()
{
int arr[] = { 1,2,3,4,5,6,7,8,9 };
printf("&arr[0] = %p\n", &arr[0]);
printf("arr = %p\n", arr);
return 0;
}
观察得到,数组名就是数组首元素的地址
但有2个例外:
1.
#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
int main()
{
int arr[] = { 1,2,3,4,5,6,7,8,9 };
printf("%d\n", sizeof(arr));
return 0;
}
如果在这段代码中,arr还是数组首元素的地址的话
那么打印结果就应该是4 或 8
但打印结果是36
注意到数组一共有 9 个 int型 的元素
数组的大小正好是36个字节
所以:sizeof(数组名)中,数组名代表的是整个数组
2.
#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
int main()
{
int arr[] = { 1,2,3,4,5,6,7,8,9 };
printf("&arr[0] = %p\n", &arr[0]);
printf("arr = % p\n", arr);
printf("&arr = %p\n", &arr);
printf("&arr[0]+1 = %p\n", &arr[0]+1);
printf("arr +1 = %p\n", arr+1);
printf("&arr +1 = %p\n", &arr+1);
return 0;
}
上面的代码示意图如下:
&arr[0] 、arr、&arr 拿到的地址相同
进行+1操作之后,
&arr[0] 、arr 都跳过4个字节,即跳过一个 int 型d的数组元素
说明它俩的指针类型相同
&arr 跳过 36 个字节,即跳过了一个数组
所以:&数组名 中, 数组名代表的是整个数组
总结:
(1)sizeof(数组名),sizeof中单独放数组名,这⾥的数组名表⽰整个数组,计算的是整个数组的⼤⼩, 单位是字节
(2)&数组名,这⾥的数组名表⽰整个数组,取出的是整个数组的地址(整个数组的地址和数组⾸元素 的地址是有区别的)
(3)除此之外,任何地⽅使⽤数组名,数组名都表⽰⾸元素的地址
2.[]下标引用操作符
#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
int main()
{
int arr[] = { 1,2,3,4,5,6,7,8,9 };
int sz = sizeof(arr) / sizeof(arr[0]);
for (int i = 0; i < sz; ++i)
printf("%d", arr[i]);
return 0;
}
打印数组元素时,使用了 [] 操作符
实际上,arr[i] 的本质是 *(arr + i)
所以就是用数组首元素的地址的移动来遍历数组
(arr + i) 与 (i + arr) 一致
所以
arr[i] == *(arr + i) == *(i + arr) == i[arr]
上述等式验证如下:
#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
int main()
{
int arr[] = { 1,2,3,4,5,6,7,8,9 };
int sz = sizeof(arr) / sizeof(arr[0]);
for (int i = 0; i < sz; ++i)
printf("%d ", arr[i]);
printf("\n");
for (int i = 0; i < sz; ++i)
printf("%d ", *(arr+i));
printf("\n");
for (int i = 0; i < sz; ++i)
printf("%d ", *(arr+i));
printf("\n");
for (int i = 0; i < sz; ++i)
printf("%d ", i[arr]);
return 0;
}
总结:
arr[i] 的本质是 *(arr + i)
数组元素的访问在编译器处理的时候,
是转换成⾸元素的地址+偏移量求出元素的地址,
然后解引⽤来访问的。
3.一维数组传参的本质
#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
void test(int arr[])
{
int sz2 = sizeof(arr) / sizeof(arr[0]);
printf("%d\n", sz2);
}
int main()
{
int arr[] = { 1,2,3,4,5,6,7,8,9 };
int sz1 = sizeof(arr) / sizeof(arr[0]);
printf("%d\n", sz1);
test(arr);
return 0;
}
x86平台运行下:
x64环境下:
main函数中,sz1,毋庸置疑,是数组元素的个数
test 函数中, 我的初心也是求传入数组的元素个数
可不管是x64还是x86环境下,结果都不正确
仔细分析:
sz2 = sizeof(arr) / sizeof(arr[0])
sizeof(arr[0]) == 4
x86环境下:
sz2 == 1,所以sizeof(arr) == 4
如果arr代表的是整个数组,那么sizeof(arr) == 36
显然arr代表的是数组首元素的地址,此时sizeof(arr) == 4
x64环境下:
sz2 == 2,所以sizeof(arr) == 8
如果arr代表的是整个数组,那么sizeof(arr) == 36
显然arr代表的是数组首元素的地址,此时sizeof(arr) == 8
总结:
本质上,数组传参传递的是数组⾸元素的地址