指针的概念
- 变量地址:系统分配给变量的内存单元的起始地址
- 指针:存放另一个变量物理地址的变量,本身也是个变量,也占有物理地址
- 通过变量名直接寻址
int k,s; scanf("%d",&k); s=3*k;
- 通过指针对变量的访问间接寻址
int *pk; //定义一个整型指针变量pk pk = &k; //pk所在的内存单元存的是k的内存地址 printf("%d",*pk); //*号表示从pk的内存单元中所指的地址中读取内容
指针的定义
- 定义格式:
类型标识符 *指针变量名
- 说明
1)*号用于定义指针变量,但指针变量名不包括*号
2)一个指针变量只能指向同一类型的变量
3)指针变量本身是整型的,指针变量本身也有自己的地址,占四个字节
指针的取值与赋值
-
取地址运算:用
&变量名
可以取得该变量的物理地址 -
取内容运算:用
*指针表达式
取得指针变量内存单元存储中存的另一个内存地址里的值 -
给指针变量赋值
1)指针变量使用前必须要有值
2)指针变量的数值必须是地址值,不能直接用一个整型赋值
3)定义格式:int a, *p = &a;
或int a,*p; p=&a;
4)可以给指针赋空值,此时指针不指向任何变量:p=NULL;
-
例子1:用直接方式和间接方式输出变量的值
#include<stdio.h> int main(){ int a,b; int *pa,*pb; a = 100;b = 10; pa = &a;pb = &b; printf("%d,%d\n",a,b); printf("%d,%d\n",*pa,*pb); return 0; }
-
例子2:将两个整型a和b按由大到小顺序输出——方法1
#include<stdio.h> int main(){ int a,b,*p1=&a,*p2=&b,*p; scanf("%d%d",&a,&b); //5 9 if(a<b){ p = p1; p1= p2; p2 = p; } printf("%d,%d\n",a,b); //5,9 printf("%d,%d\n",*p1,*pb);// 9,5 return 0; }
-
例子3:将两个整型a和b按由大到小顺序输出——方法2
#include<stdio.h> int main(){ int a,b,*p1=&a,*p2=&b,*p; scanf("%d%d",&a,&b); //5 9 if(a<b){ p = *p1; //将p1所指的内容赋值给p *p1= *p2; *p2 = p; } printf("%d,%d\n",a,b); //9,5 printf("%d,%d\n",*p1,*pb);// 9,5 return 0; }
指针的算数运算
指针本质也是个变量,在自己的物理地址里存的是别人的物理地址
物理地址是个数字,所以可以对指针进行算数运算
-
递增一个指针
#include <stdio.h> #define MAX 3 int main () { int var[] = {10, 100, 200}; int i, *ptr; /* 指针中的数组地址 */ ptr = var; // 数组名存放的就是首元素的物理地址 for ( i = 0; i < MAX; i++) { printf("存储地址:var[%d] = %x\n", i, ptr ); printf("存储值:var[%d] = %d\n", i, *ptr ); /* 移动到下一个位置 */ ptr++; } return 0; }
结果如下:
存储地址:var[0] = bf882b30 存储值:var[0] = 10 存储地址:of var[1] = bf882b34 存储值: var[1] = 100 存储地址:of var[2] = bf882b38 存储值:var[2] = 200
-
递减一个指针
#include <stdio.h> #define MAX 3 int main () { int var[] = {10, 100, 200}; int i, *ptr; /* 指针中最后一个元素的地址 */ ptr = &var[MAX-1]; for ( i = MAX; i > 0; i--) { printf("存储地址:var[%d] = %x\n", i-1, ptr ); printf("存储值:var[%d] = %d\n", i-1, *ptr ); /* 移动到下一个位置 */ ptr--; } return 0; }
结果如下:
存储地址:var[2] = 518a0ae4 存储值:var[2] = 200 存储地址:var[1] = 518a0ae0 存储值:var[1] = 100 存储地址:var[0] = 518a0adc 存储值:var[0] = 10
-
指针的比较
物理地址本质上也是个整型数,所以也可以比较大小,因此存放地址的指针也可以比较大小#include <stdio.h> #define MAX 3 int main () { int var[] = {10, 100, 200}; int i, *ptr; /* 指针中第一个元素的地址 */ ptr = var; i = 0; while ( ptr <= &var[MAX - 1] ) { printf("Address of var[%d] = %p\n", i, ptr ); printf("Value of var[%d] = %d\n", i, *ptr ); /* 指向上一个位置 */ ptr++; i++; } return 0; }
结果如下:
Address of var[0] = bfdbcb20 Value of var[0] = 10 Address of var[1] = bfdbcb24 Value of var[1] = 100 Address of var[2] = bfdbcb28 Value of var[2] = 200
指针与数组
C语言中凡是可以通过数组下标方式完成的操作,都可以用指针的方式实现
例如:利用指针输入和输出数组全部元素
#include<stdio.h>
int main(){
int a[10],i,*p=a;
for(i=0;i<10;i++,p++){
scanf("%d",p);
}
printf("\n");
for(p=a;p<a+10;p++){
printf("%d ",*p);
}
return 0;
}
存放指针的数组:指针数组
-
指向整型的指针数组
#include <stdio.h> const int MAX = 3; int main () { int var[] = {10, 100, 200}; int i, *ptr[MAX]; for ( i = 0; i < MAX; i++) { ptr[i] = &var[i]; /* 赋值为整数的地址 */ } for ( i = 0; i < MAX; i++) { printf("Value of var[%d] = %d\n", i, *ptr[i] ); } return 0; }
-
指向字符的指针数组
#include <stdio.h> const int MAX = 4; int main () { const char *names[] = { "Zara Ali", "Hina Ali", "Nuha Ali", "Sara Ali", }; int i = 0; for ( i = 0; i < MAX; i++) { printf("Value of names[%d] = %s\n", i, names[i] ); } return 0; }
指针与函数
-
指针变量作为函数参数:将一个变量的地址传送到另一个函数中
被调用函数不能改变实参指针变量的值,但可以改变实参指针变量所指向的变量的值
1)输出字符串#include<stdio.h> void display(char *t){ char s[] = "Happy"; printf("%s\n",t); t = s; printf("%s\n",t); } int main(){ char *p = "Teacher"; display(p); printf("%s\n",p); return 0; }
2)使用指针实现数组元素逆序存放
#include<stdio.h> void reverse(int *p,int n){ int *q,t; for(q=p+n-1;p<q;p++,q--){ t=*p; *p=*q; *q=t; } } int main(){ int a[10] = {1,2,3,4,5,6,7,8,9,10}; int i; reverse(a,10); for(i=0;i<10;i++){ printf("%d ",a[i]); } return 0; }
-
数组名作为函数参数
1)将数组名作为参数传递给函数,本质上就是将数组首元素的地址传递给了函数。
2)也可以说是一个存着数组首地址的指针传递给了函数,所以本质上和指针变量作为参数是一样的
3)当用数组名作为参数时,形参数组中元素的值发生改变,实参数组元素中的值也会改变