1.数组名的理解
用这段代码,看一下 arr ; &arr ; &arr[0] 有什么区别
#include<stdio.h>
int main()
{
int arr[10]={0};
printf("%p\n",arr);
printf("%p\n",&arr);
printf("%p\n",&arr[0]);
return 0;
}
一样的地址,说明此时三种写法都表示数组中第一个元素的地址
直接用数组名(arr)等价于 &arr[0] ,表示第一个元素的地址(但又两个例外,写后面了)
再用这个代码看看区别:
#include<stdio.h>
int main()
{
int arr[10] = { 0 };
printf("arr =%p\n", arr);
printf("arr+1 =%p\n", arr + 1);
printf("&arr =%p\n", &arr);
printf("&arr+1 =%p\n", &arr+1);
printf("&arr[0] =%p\n", &arr[0]);
printf("&arr[0]+1 =%p\n", &arr[0]+1);
return 0;
}
&arr与&arr+1相差 40 个字节,其他两组相差 4 个字节
而arr中 10 个元素占的内存正好为 40 个字节
所以,写成&数组名 表示取整个数组的地址,而非数组首元素的地址
这是第一个例外(上面提到了)
第二个:
sizeof(arr):这里arr也表示取整个数组的地址,计算的是整个数组占的字节数
总结两例外:
1. &(数组名):表示取出整个数组的地址
2. sizeof(数组名):数组名表⽰整个数组,计算的是整个数组的⼤⼩,
单位是字节
2.使用指针访问数组
写段代码,输入数组中元素后输出
#include<stdio.h>
int main()
{
int arr[10]={0};
int i=0;
int* p=arr;
int sz=sizeof(arr)/sizeof(arr[0]);
for(i=0;i<sz;i++)
{
scanf("%d",p);
p+=i;
}
p=arr;
for(i=0;i<sz;i++)
{
printf("%d ",*(p+i));
}
return 0;
}
此代码中,p与arr是等价的,既然arr[i]可以访问数组元素,那么 p[i] 也可以访问数组元素
总结一下:(准备好下巴)
arr[i] 等价于 p[i]
arr[i] 本质上是 *(arr+i) == * (p+i)
*(arr+i)= * (i+arr) 即:arr[i]=i[arr] p[i]=i[p]
*arr[i] = (arr+i)= * (i+arr) = i[arr]
再改一次验证一下:
看一段问题代码:
#include <stdio.h>
void test(int arr[])
{
int sz2 = sizeof(arr) / sizeof(arr[0]);
printf("sz2 = %d\n", sz2);
}
int main()
{
int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
int sz1 = sizeof(arr) / sizeof(arr[0]);
printf("sz1 = %d\n", sz1);
test(arr);
return 0;
}
sz2的问题在于,传参时传的是首元素的地址,而sizeof 此时计算的只能是首元素的内存字节
3.传址调用
写一个函数,实现两个变量间值的交换:
问题代码:
#include<stdio.h>
void Switch(int x ,int y)
{
int temp=0;
temp=x;
x=y;
y=temp;
}
int main()
{
int a=5;
int b=3;
printf("%d %d\n",a,b);
Switch(a,b);
printf("%d %d\n",a,b);
}
问题在于:实参 a,b和形参 x,y存放的不是同一块内存,函数中的 x,y只是接受了a,b的值,就算x,y的值在函数里发生交换,也不会影响a,b的值
此时就需要把 a,b的地址分别传给x,y
用指针:
#include<stdio.h>
void Switch(int* x, int* y)
{
int temp = 0;
temp = *x;
*x = *y;
*y = temp;
}
int main()
{
int a = 5;
int b = 3;
printf("%d %d\n", a, b);
Switch(&a, &b);
printf("%d %d\n", a, b);
}
这就是传址调用