指针的理解
void f(int *p){//在调用时得到了某个变量的地址,在函数里面可以通过指针访问外面的i
printf("p = %p\n",p);
printf("*p = %d\n",*p);//*的作用:通过读取地址获得变量的值
*p = 26;//在函数内部,通过指针更改外部变量对应的值
}
int main(){
int i = 6;
printf("i = %d",i);//输出6
printf("p = %p\n",&i);
f(&i);
printf("i = %d",i);//经过f函数通过调用指针更改外部值之后,输出26
}
//*是一个单目运算符,用来访问指针上的值表示的地址上的变量、可以做右值、也可以做左值
//比如:int k = *p(右值、访问用) *p = k+1 (左值、改变用)
指针的应用场景【1】——交换两个变量的值
void swap(int *pa,int *pb){
int t = *pa;
*pa = *pb;
*pb = t;
}
int main(){
int a = 5;
int b = 6;
swap(&a,&b);
printf("a = %d\n",a);
printf("b = %d\n",b);
return 0;
}
指针的应用场景【2】——函数返回多个值(*常考)
选取数组内的最大值和最小值
void minmax(int len,int *pa,int*pb,int a[]){
int i;
*pa = *pb = a[0];
for(i=0;i<len;i++){
if(a[i]>*pa){
*pa = a[i];//*pa为返回的最大值//
}
if(a[i]<*pb){
*pb = a[i];//*pb为返回的最小值//
}
}
}
void minmax(int len,int *pa,int*pb,int a[]);
int main(){
int a[] = {1,2,3,4,5,6,7,8,9,-1,22,55,23,-2};
int min,max;
minmax(sizeof(a)/sizeof(a[0]),&max,&min,a); //sizeod(a)/sizeof(a[0])是常用的调用数组长度的方法//
printf("min = %d\n",min);
printf("max = %d\n",max);
return 0;
指针的应用场景【3】——函数返回运算的状态,结果通过指针返回
int divide(int a,int b,int *result);
int divide(int a,int b,int*result){
int ret = 1;
if(b == 0){
ret = 0;
}
else{
*result = a/b;
}
return ret;
}
int main(){
int a = 5;
int b = 2;
int c;
if(divide(a,b,&c)){
printf("%d/%d = %d\n",a,b,c);
}
return 0 ;
}
注意:在定义指针之后,一定要先将其指向变量,再使用;而不能在未将其指向变量的时候就对其赋值等操作
数组和指针
数组本质:指针
因此:
- 可以在函数内,对数组操作,更改其包含的元素
- 可以在函数内,读取外部数组的存储位置(在函数内外以%p的形式打印,得到的值相同)
- 可以在函数内定义数组参数时,将其改写为数组形式,当a为数组时,以下两种表达方式是等价的
int f(int a[])
int f(int *a)
- 不能在定义函数的数组参数时,指定其长度
- 不能在定义函数时,通过“sizeof(a)/sizeof(a[0])”(a是数组)的方式计算数组的长度
数组变量是特殊的指针
1.数组本身表达地址
- 数组本身无需通过 & 取其对应的地址,如:int a[10];取其地址:
int *p = a
(且 a == &a[0]) - 数组内元素需通过 &取其对应的地址
2.[]运算符可以对数组做,也可以对指针做
p[0]<==>a[0]
3.运算符可以对指针做,也可以对数组做
4.数组变量是const的指针,所以不能被赋值
int b[] -- >int *const b
区分指针是const(数组情况) & 指针指向const
1.指针本身是const
表示一旦得到了某个变量的地址,不能再指向其他变量
int *const q = &i;
*q = 26; //OK 可以通过指针去修改变量,但是指针指向的变量是不变的
q++; //Error
2.指针所指是const
表示不能通过指针去修改那个变量(并不能使得那个变量成为指针)
const int *p = &i;
*p = 26; //ERROR 不能通过指针更改变量
i = 26; //OK
p = &j; //OK
总结:判断哪个被const了的标志是const 在 * 的前面还是 * 的后面
1.* ... const
:表示指针获得某个变量地址之后不能更改
2.const ..*
:表示指针指向的变量是const
int i;
const int *p = &i;
int const *p = &i;//与上一行表示的意思一样
int *const p = &i;
*p++
- 取出p所在的位置,完事之后顺便把p移到下一个位置去
*
的优先级虽然高,但是没有++
高- 常用于数组的连续空间操作
- 在某些cpu上,可以直接被翻译成一条汇编指令
关于指针的运算:
- 可以做比较、
- 可以作加减、
- 但是不可以作乘除
0地址
内存中有0地址,但是0地址通常是个不能随便碰的地址
指针不应该具有0值
因此可以用0指针表示特殊的事:
- 返回的指针是无效的
- 指针没有被真正的初始化
Null是一个预定定义的符号,表示0地址
有的编译器不愿意使用0表示0地址
指针的类型
无论是什么类型,所有的指针大小都是一样的,因为都是地址
指向不同类型的指针不能直接相互赋值,这是为了避免用错指针
指针的类型转化
void* 表示不知道指向什么东西的指针
计算时与char*相同(但不相通)
指针可以转化类型
int *p = &i;
void *q = (void*)p;
上述代码并没有改变p所指向的变量的类型,而是让后人用不同的眼光看p所指的变量
用指针做什么
需要传入较大的数时用作参数
传入数组后对数组进行操作
函数返回不止一个结果
需要用函数修改不止一个变量
动态的申请内存