指针的使用
指针的应用场景
一
- 交换两个变量的值
void swap(int *pa,int *pb)
{
int t = *pa;
*pa = *pb;
*pb = t;
}
二
- 函数返回多个值,某些值只能通过指针返回
- 传入的参数实际上是需要保存带回的结果的变量
- 函数返回运算的状态,结果通过指针返回
- 常用的套路就是让函数返回特殊的不属于有效范围内的值来表示出错
- -1或0(在文件操作会看到大量的例子)
- 但是当任何数值都是有效的可能结果时,就得分开返回了
#include <stdio.h>
int div(int a,int b,int* result)
{
int ret = 1;
if(b == 0)ret = 0;
else{
*result = a/b;
}
return 0;
}
int main()
{
int a = 5;
int b = 2;
int c;
if(div(a,b,&c))
{
printf("%d/%d = %d\n",a,b,c);
}
return 0;
}
传入函数的数组成了什么?
int isprime(int x, int arr[],int len)
{
int ret = 1;
for(int i = 1; i < len; i++)
{
if(x % arr[i] == 0)
{
ret = 0;
break;
}
}
return ret;
}
- 函数参数表中的数组实际上是指针
- sizeof(arr) == sizeof(int*)
- 但是可以用数组的运算符[]进行运算
以下四则函数原型等价
int sum(int *arr,int n);
int sum(int *,int);
int sum(int arr[],int n);
int sum(int [],int);
数组变量是特殊的指针
- 数组变量本身表达地址,所以
- int a[10]; int*p = a //不需要用&取地址
- 但是数组的单元表达的是变量,需要用&取地址,a == &a[0]
- []运算符可以对数组做也可以对指针做
- p[0] <==> a[0]
- *运算符可以对做指针也可以对数组做
- *a = 25
- 数组变量是const的指针,所以不能被赋值
- int a[] <==> int * const a =
指针与Const
指针是const
- 表示一旦得到了某个变量的地址,不能再指向其他变量
int *const q = &a; //q是const
*q = 26; //OK
q++; //error
所指是const
- 表示不能通过这个指针去修改那个变量(并不能使得那个变量成为const)
const int *p = &a;
*p = 26; //error(*p)是const
i = 26; //OK
p = &j; //OK
判断那个被const了的标志是const在*前面还是后面
int a;
const int* p1 = &i;
int const* p2 = &i;
int *const p3 = &i;
//上面两个等价,指的是它所指的东西不能被修改
//下面那个指的是指针不能被修改
转换
- 总是可以把一个非const的值转换成const的
void f(const int *x);
int a = 5;
f(&a); //OK
const int b = a;
f(&b); //OK
b = a + 1; //error
当要传递的参数的类型比地址大的时候,这是常用的手段,既能用比较少的字节数传递值给参数,又能避免函数对外面的变量的修改
const数组和保护数组值
const int a[] = {1,2,3,4,5,6};
- 数组变量已经是const的指针了,这里的const表明数组的每个单元都是const int
- 所以必须通过初始化进行赋值
int sum(const int a[],int n);
- 因为把数组传入函数时传递的是地址,所以那个函数内部可以修改数组的值
- 为了保护数组不被函数破坏,可以设置成上面这种const
指针的运算
- 不同类型的数组的指针在经过偏移的时候,地址的偏移量和数组类型相关
char arr[10]={0,1,2,3,4,5,6,7,8,9};
char *p = arr;
printf("p = %p\n",p);//如果结果为0x12
printf("p + 1 = %p\n",p+1);//那么p+1就是0x13
int brr[10]={0,1,2,3,4,5,6,7,8,9};
int *q = brr;
printf("q = %p\n",q);//如果结果是0x20
printf("q + 1 = %p\n",q); //那么q+1的结果就是0x24
所以指针p+1 <==> p+sizeof(类型)
- 以下这些运算可以对指针进行操作
- 给一个指针加减一个整数(+、-、+=、-=)
- ++ 、–
- 两个指针相减
char arr[10]={0,1,2,3,4,5,6,7,8,9};
char *p = arr;
char *p1 = &arr[5]
printf("p1-p = %d\n",p1-p);//5
- 指针中的0地址,我们一般初始化指针但不赋值的时候初始化为NULL
动态分配内存(malloc和free)
函数
#include <stdlib.h>
void* malloc(size_t size);
void* free(fp);//要是否申请空间的首地址
向malloc申请的大小是以字节为单位的
返回值是void*类型的,我们可根据自己的需要进行转换
(int *)malloc(n*sizeof(int));
malloc得到的空间是连续的吗?
程序上看到的空间是连续得,实际内存的比分配的大,因为操作系统是分页管理,实际的物理内存可能非连续