目录
运算符&的“前世今生”
刚开始接触C语言时,我们就得记住一件事,scanf()中输入一个变量,变量前必须加“&”,否则就会报错,而printf()中却不用。
要知道它的作用,就先从变量入手。编辑
C语言的变量放在内存里,因此有一个占据的地方,就是地址。而“&”就是把变量的地址拿出来,告诉你这个变量放在哪里,然后取出调用
&也有地址,在printf() 中可用%p求出
intmain(){ inti=0; printf("%p\n",&i); return0; }
而地址的大小是否与int相同,则取决于编译器
取地址时&右边必须是明确的变量,不能为表达式编辑
相邻地址间的差距永远是4
intmain(void) { inta[10]; printf("%p\n",&a); printf("%p\n",a); printf("%p\n",&a[0]); printf("%p\n",&a[1]); return0; }
编辑
指针
需要一个参数保存变量的地址,则可以使用指针
指针类型的变量就是保存地址的变量编辑
int* p = &i; 就是把i的地址保存到指针p中,其中*可以靠近int 也可以靠近p
int* p,q;等价于int *p,q;我们就可以说p指向了q
指针变量的值是具有实际值的变量的地址,而普通变量的值是实际的值
voidf(int*p); intmain(void) { inti=6; printf("&i=%p\n",&i); f(&i); system("pause"); return0; } voidf(int*p) { printf("p=%p\n",p); }
可见输出结果中p已经保存了i的地址,使得f函数拥有访问外面i的能力了,可是该怎么访问,即怎样读或写?
其实只需使用*加指针变量即可,同上代码,可以把*p理解成一个整数
在f函数中加入一句
printf("*p = %d\n",*p);
这时输出的数值即为6,就是i的初值,可见使用*加上指针变量就能访问这个地址
修改外部的值
按照之前的课程,我们知道函数是独立程序模块,不能将外部定义的值修改,而此时有了指针,在函数中获取了地址,则情况就不一样了
voidf(int*p); voidg(intk); intmain(void) { inti=6; printf("&i=%p\n",&i); f(&i); g(i); system("pause"); return0; } voidf(int*p) { printf("p=%p\n",p); printf("*p = %d\n",*p); *p=26; } voidg(intk) { printf("k =%d",k); }
f函数里的*p保存了i的地址,在这个函数指向i,此时对*p赋值,也就相当于对i值进行了改变,实现了对外链接,i的值变为了26,就是芥末神奇编辑
指针的应用
一、交换两个变量的值
当我们学到函数时,尝试过利用函数交换两个数,结果可想而知,无法改变函数外a,b的取值
编辑
但这却可以用指针来解决
voidswap(int*pa,int*pb); intmain() { inta=5; intb=6; swap(&a, &b); printf("a=%d,b=%d",a,b); return0; } voidswap(int*pa, int*pb) { intt=*pa; *pa=*pb; *pb=t; }
运行后a与b 的值发生了互换
返回多个值
函数中return语句只能传出一个变量值,函数结果不止一个时可以用指针传出
voidminmax(inta[],intlen,int*max,int*min); intmain(void) { inta[] = {1,2,3,4,5,6,7,8,9,12,13,14,16,17,21,23,55,}; intmin,max; minmax(a,sizeof(a)/sizeof(a[0]),&min,&max); printf("min=%d,max=%d",min,max); return0; } voidminmax(inta[],intlen,int*min,int*max) { inti; *min=*max=a[0]; for(i=1;i<len;i++){ if(a[i]<*min){ *min=a[i]; } if(a[i]>*max){ *max=a[i]; } } }
以此代码为例,在minmax函数中找出素数最大与最小值,用指针便可传递两值离开函数,并在主函数中printf输出
指针与数组
函数参数表中的数组实际上是指针,但可以用数组的运算符 [ ] 进行运算
sizeof(a)==sizeof(int*)
数组变量本身表达地址,所以在数组无需用&取地址即int a[10]; int *p=a;
但数组的单元表达是变量,如a[0],a[1]···等等,需要用&取地址
a==&a[0] 运算符 [ ] 可以对数组做,也可以对指针做:*p<==>p[0]
相反,*也可以对数组做:*a<==>a[0]
指针这个知识点是真滴生涩,看不懂啊喂 QwQ
编辑
数组变量是const的指针,所以不能被赋值,数组变量间不能做赋值
错误示范:a[ ]=b或者int a[ ];a=b;
一个数组是常量指针,即const的指针,所以不能被赋值
int a[ ]<==>int *const a=···
const int a[]={1,2,3,4,5,6};数组变量本身是const指针
这里的const表明数组的每个单元都是const int,所以必须通过初始化进行赋值,否则接下来将不能进行赋值操作
希望数组在函数中不被破坏,可以设置参数为const
int sum(const int a[],int length);
指针与常量
指针是const时,表示一旦得到了某个变量的地址,不能再指向其他变量,即关系一定,指针一定指向某个变量,不会被改变
①int *const q = &i
(q是const)q指向了i这个事实不可改变,它们之间的关系是永久的
此时以*q = 26为例,是可以做的,因为i不是const,i可以赋初值,使 i=26,但因为q是const,所以q++的做法是错误的
②const int *p = &i
表示不能通过p这个指针去修改i这个变量,即*p=26是错误的,不能让 i=26,此时的*p是const
但i不是const,可以单独给i赋值,i=26而不能通过*p去改变。同时p不是const,它也可以指向其他地址,p = &j;是成立的
总的来说,有两种意思:一是指针不可修改,另一是不可通过指针修改
const在*前,表面它所指的东西不能修改
const在*后,表面指针不能被修改
指针的运算
intmain() { charac[]={0,1,2,3,4,5,6,7,8,9,}; char*p=ac; printf("p=%p\n",p); printf("p+1=%p\n",p+1); charai[]={0,1,2,3,4,5,6,7,8,9,}; char*q=ai; printf("q=%p\n",q); printf("q+1=%p\n",q+1); return0; }
让指针加1:sizeof(char)=1,sizeof(int)=4
由上面的代码运行可知,char的指针地址加1,而int时,变成了加4。所以指针加1,并不是在地址值上加1,而是在地址值上加一个sizeof那个指针所指的类型
int一个单元占4个字节,所以2c加1后单元地址为30,再加1,则为34
对指针做加一,实际上是我们把它移到下一个单元去
*p ->ac[0] 所以*(p+1)->ac[1]
intmain() { charac[]={0,1,2,3,4,5,6,7,8,9,}; char*p=ac; printf("*p=%d\n",*p); printf("*(p+1)=%d\n",*(p+1)); return0; }
运行代码可见,*p确实输出为0与ac[0]相同
而*(p+1)为1,与ac[1]相同===================》》》》》*(p+n)与a[n]是一回事儿
如果指针不是指向一片连续分配的空间,如数组,则这种运行没有意义
指针计算
1.给指针加减一个整数(+,+=,-,-=)
2.递增递减(++,--)
3.两个指针相减(所得结果不是两个地址的差,而是差,除以sizeof的类型,表示在这两者间有多少个单元在里面)
intmain() { charac[]={0,1,2,3,4,5,6,7,8,9,}; char*p=ac; char*p1=&ac[5]; printf("p1-p=%d\n",p1-p); charai[]={0,1,2,3,4,5,6,7,8,9,}; char*q=ai; char*q1=&ai[5]; printf("q1-q=%d\n",q1-q); system("pause"); return0; }
*p++
取出*p所指的那个数据来,再顺便把p移到下一位
*优先级虽然高,但没有++高,所以不需要再加括号变成*(p++)
*p++常用于数组类的连续空间操作
intmain(void) { chara[]={0,10,25,37,49,52,65,76,83,95,-1}; char*p=&a[0]; for(p=a;*p!=-1;*p++){ printf("%d\n",*p); } return0; }
指针比较
<,<=,==,>=,>,!=都可以对指针进行比较内存中的地址
数组中的单元地址肯定是线性递增
指针类型
无论指向什么类型,所有指针的大小都是一样的,因为都是地址,但指向不同类型的指针是不能直接相互赋值的
编辑