- 取地址运算
运算符 &
scanf("%d",&i);里的&,作用是获取变量的地址,它的操作数必须是变量
int i;
printf("%x",&i);
地址的大小是否与int相同取决于编译器
int i;
printf("%p",&i);
&不能对没有地址的东西取地址
eg:&(a+b)、&(a++)、&(++a)
可取
1)变量的地址
2)相邻变量的地址
3)&的结果的sizeof
#include<stdio.h>
int main(void)
{
int i = 0;
int p;
printf("%p\n",&i);
printf("%p\n",&p);
return 0;
}
4)数组的地址
5)数组单元的地址
6)相邻的数组单元的地址
#include<stdio.h>
int main(void)
{
int a[10];
printf("%p\n",&a);
printf("%p\n",a);
printf("%p\n",&a[0]);
printf("%p\n",&a[1]);
return 0;
}
- 指针
保存地址的变量
int i;
int* p = &i; //* p 表示p是一个指针,指向int
int* P,q; //*位置可以靠近int,但q只是一个普通的int类型的变量
int *p,q; //*位置也可以远离int, · ·
- 指针变量
变量的值是内存的地址
普通变量的值是实际的值
指针变量的值是具有实际值的变量的地址
- 作为参数的指针
void f(int *p); //f需要一个int的指针,在被调用的时候得到了某个变量的地址
int i = 0;
f(&i); //在函数里面可以通过这个指针访问外面这个i
#includ<stdio.h>
void f(int *p);
int mai(void)
{
int i = 6;
printf("&i=%p\n",&i);
f(&i);
return 0;
}
void f(int*p)
{
printf("p=%p\n",p);
}
- 访问地址上的变量*
*是一个单目运算符,用来访问指针的值所表示的地址上的变量,可以做右值也可以做左值
int k = *p;
*p = k+1;
#include<stdio.h>
void f(int *p);
void g(int k);
int main(void)
{
int i = 6;
printf("&i=%p\n",&i);
f(&i);
g(i);
return 0;
}
void f(int *p)
{
printf(" p=%p\n",p);
printf("*p=%d\n",*p); //通过p指针访问到了p所指的int i里面的值
*p = 26; //得到k = 26
}
void g(int k)
{
printf("k=%d\n",k);
}
*左值之所以叫左值,是因为出现在赋值号左边的不是变量,而是值,是表达式计算的结果:a[0] = 2;、*p = 3;是特殊值
- 指针的运算符&*
互相反作用
*&yptr -> * (&yptr) -> *(yptr的地址) -> 得到那个地址上的变量 -> yptr
&*yptr -> &(*yptr) -> &(y) -> 得到y的地址,也就是yptr -> yptr
- 传入地址
- 指针的使用
应用场景一
交换两个变量的值
#include<stdio.h>
void swap(int *pa, int *pb);
int main(void)
{
int a = 5;
int b = 6;
swap(&a,&b);
printf("a=%d,b=%d\n",a,b);
return 0;
}
void swap(int *pa, int *pb);
{
int t = *pa;
*pa = *pb;
*pb = t;
}
应用场景二
a、函数返回多个值,某些值就只能通过指针返回,传入的参数实际上是需要保存待会的结果的变量
#include<stdio.h>
void minmax(int a[], int len, int *max, int *min);
int main(void)
{
int a[] = {1,2,3,4,5,6,7,8,9,12,13,14,16,17,21,23,55,};
int min,max;
minmax(a, sizeof(a)/sizeof(a[0]),&min,&max);
printf("min=%d,max=%d\n",min,max);
return 0;
}
void minmax(int a[], int len, int *min, int *max)
{
int i;
*min = *max = a[0];
for ( i=1; i<len; i++)
{
if( a[i] < *min )
{
*min = a[i];
}
if( a[i]> *max )
{
*max = a[i];
}
}
}
b、函数返回运算的状态,结果通过指针返回。常用套路是让函数返回特殊的不属于有效范围内的值来表示出错:-1或0,但是当任何数值都是有效的可能结果时,就得分开返回,状态用函数的return返回,实际值通过指针参数返回
- 指针的常见错误
定义了指针变量,还没有指向任何变量,就开始使用指针
- 指针与数组
函数参数表中的数组实际上是指针,sizeof(a) == sizeof(int*),但是可以用数组的运算符[ ]进行运算
- 数组参数
以下四种函数原型是等价的:
int sum(int *ar,int n);
int sum(int *,int);
int sum(int ar[],int n);
int sum(int [],int n);
数组变量是特殊的指针
数组变量本身表达地址,所以
int a[10];
int*p = a; //无需用&取地址
//但数组的单元表达是变量,需要用&取地址
a == &a[0]
[ ]运算符可以对数组做,也可以对指针做:
p[0] <==> a[0]
*运算符可以对指针做,也可以对数组做:
*a = 25;
数组变量时const的指针,所以不能被赋值