1.指针存在的意义
1.提供一种对内存空间的访问形式,可以让程序更加简洁、高效
2.提供一种对变量的间接访问,通过找到变量在内存中的位置来操作变量
2.指针相关的概念
1.内存:存放数据的空间,以字节来编址
2.地址:用来区分内存中不同字节的编号,称为地址
3.指针:指针就是地址,地址就是指针
4.指针变量:是一个变量,占8个字节空间,存放指针(地址)的变量,有时也会简称为指针
3.指针相关的运算符
1. & :获得变量在内存空间中的首地址
1.只有变量能够&操作,常量和表达式不能&操作(只有左值能够&操作)
2.表达式的值为:变量在内存空间中的首地址
3.&具有类型升级的效果, &Num 得到 int * 型
2. *:获得指针对应空间中的值
1.作为右值
1.根据类型指针类型决定取得的数据字节数
2.可以让类型降级,int * -> * 得到 int 类型
2.作为左值
*p = 200, 将右值赋值给指针指向的空间
3.注意
&和*连用效果会抵消掉 *&Num == Num
4.指针变量的定义
1.定义形式
数据类型* 变量名;
int *p;
double *p;
float *p;
char *p;
short *p;
int *p, *q;
2.指针变量的初始化
1.未经初始化的指针,或指向一段被释放过空间的指针称为野指针
2.指针定义后都要进行初始化,初始化为NULL (指向内存地址0x0) int *p = NULL;
3.指针的算数运算
+
-
++:向内存高地址偏移指向数据类型大小个字节空间
--:向内存低地址偏移指向数据类型大小个字节空间
注意:
int *p = NULL;
int *q = NULL;
若干代码;
p-q 两个地址中间相差了多少个整形元素
4.不同类型指针的特点:
1.*操作时取得的空间大小不一致
2.算数运算时偏移量不同
5.指针常见操作
int a = 100;
int b = 200;
int *p = &a;
int *q = &b;
1.p = &b;
2.*p = b;
3.p = q;
4.*p = *q;
6.指针作为函数参数
地址传递:将实参的地址给了形参,形参是指向实参的指针,可以利用形参修改实参的值
注意:
1.函数体内部想使用函数体外部变量值的时候使用值传递
2.函数体内部想修改函数体外部变量值的时候使用地址传递
7.指针和数组的关系
int a[5] = {1, 2, 3, 4, 5};
int *p = NULL;
p = &a[0];
数组的数组名是指向数组第一个元素的指针常量
访问数组下标为n的元素的方式为:
a[n] == *(a+n) == *(p+n) == p[n]
注意:
1.C语言中所有指针都可以使用[]来访问元素
2.指针[下标] == *(指针 + 下标)
3.数组的数组名类型理解为int *型,除以下两种情况
(1)sizeof运算时
(2)&运算时
4.存放元素使用数组,操作元素使用指针
8.数组作为函数参数
int a[5] = {1,2,3,4,5};
int fun1(int array[], int len);
int fun2(int array[5]);
int fun3(int *parray, int len);
小练习:
1. 封装一个函数从终端接收5个数到整形数组中
封装函数实现将5个元素的数组完成倒置
封装函数实现将5个元素的数组值完成打印
#include
int Input(int *parray, int len)
{
int i = 0;
while(i < len)
{
scanf("%d", &parray[i]);
i++;
}
return 0;
}
int Output(int *parray, int len)
{
int i = 0;
while(i < len)
{
printf("%d ", parray[i]);
i++;
}
printf("\n");
return 0;
}
int DaoZhi(int *parray, int len)
{
int i = 0;
int tmp = 0;
while(i < len / 2)
{
tmp = parray[i];
parray[i] = parray[len-1-i];
parray[len-1-i] = tmp;
i++;
}
return 0;
}
int main(void)
{
int a[5] = {0};
Input(a,5);
DaoZhi(a,5);
Output(a,5);
return 0;
}
2.封装一个函数从终端接收5个数到整形数组中
封装一个函数获得这个数组中的最大值和最小值
#include
int Input(int *parray, int len)
{
int i = 0;
while(i < len)
{
scanf("%d",&parray[i]);
i++;
}
return 0;
}
int fun(int *parray, int len, int *pmaxnum, int *pminnum)
{
int i = 0;
int max = 0;
int min = 0;
for(i = 1; i < len; i++)
{
if(parray[max] < parray[i])
{
max = i;
}
if(parray[i] < parray[min])
{
min = i;
}
}
*pmaxnum = parray[max];
*pminnum = parray[min];
// printf("max = %d\n",parray[max]);
// printf("min = %d\n",parray[min]);
return 0;
}
int main(void)
{
int a[5] = {0};
int max = 0;
int min = 0;
Input(a, 5);
fun(a,5,&max,&min);
printf("max = %d\n",max);
printf("min = %d\n",min);
return 0;
}
3. 封装一个函数从终端获得若干个数(n <= 10 以-1结尾)到整形数组中
封装一个函数获得数组元素的平均值
#include
int Input(int *parray, int len)
{
int i = 0;
for(i = 0; i < len; i++)
{
scanf("%d", &parray[i]);
if(parray[i] == -1)
{
break;
}
}
return i;
}
int Average(int *parray, int len, double *Avenum, int geshu)
{
int i = 0;
int sum = 0;
for(i = 0; i < geshu; i++)
{
sum += parray[i];
}
*Avenum = (double)sum / geshu;
return 0;
}
int main(void)
{
int a[10] = {0};
double ave = 0;
int geshu = 0;
geshu = Input(a,10);
Average(a,10,&ave,geshu);
printf("平均值为:%.2lf\n",ave);
return 0;
}