1.什么是地址: 我们说变量都有自己的地址, 计算机要找到某个变量,必须知道该变量的地址.我们可以通过 & 获得变量地址
取地址符 : & 通过取地址符就能把变量的地址给取出来.
int main(int argc, const char * argv[]) { int a; printf("%p ", &a);//输出变量a的地址 return 0; }
2.什么是指针?
假如我们拥有很多客户的地址, 那么我们需要一个通讯录来保存这些客户的地址, 同样对于计算机来说, 也需要用一个工具来保存变量的地址, 那么这个工具,就是指针
指针就是用来保存内存地址的变量,本质是变量,变量存放的是地址,指针变量同样具有变量名,变量类型,变量值
我们可以通过图形来表示
指针定义:
一般形式: 类型 * 标示符
标示符: 表示指针变量的名字
类型: 表示指针指向的数据类型
int main(int argc, const char *argv[]) { int a; int *p;// 定义一个指针类型的变量p p= &a;//取出a的地址赋值给指针p printf("%p ", p); printf("%p ", &a); return 0; }
3.间接寻址符: *
通过指针进行读取
如果知道图书馆的地址, 那么我们可以找到图书馆,并在图书馆内阅览;
同理, 如果指针p保存了变量a的地址, 那么就可以通过指针p来找到变量a, 并读取变量a 的值
通过指针进行修改
只要知道某一个人的地址, 那么我们就能找到这个人
同理, 知道变量的地址,那么我们就能修改变量的值
/* int main(int argc, const char *argv[]) { int a= 10; int *p= &a; printf("a== %d ", *p); return 0; } */ int main(int argc, const char *argv[]) { int a= 10; int *p= &a;//取出地址并赋值 *p = 20;//修改变量a的值 printf("a == %d", a); return 0; }
4.void * 指针
#define NULL ((void *) 0)
空指针 NULL #define NULL ((void *)0)
指针就是用来保存内存地址的变量, 因此定义一个指针后一定要用它来保存一个内存地址, 假如不那么做, 那么该指针就是一个野指针, 它的默认值是随机的, 因此会造成混乱
int main(int argc, const char *argv[]) { int a = 10; char ch = 'a'; void *p=&a; void *q = &ch; // *p = 10; printf("%d ", *(int *)p); printf("%c ",*(char *)q); //printf("%d", *p); return 0; }
5.野指针
(1)当一个指针指向内容非法时, 那这就是一个野指针
(2)定义一个指针没有赋初值, 这个指针就是野指针
(3)一个指针指向的内容被销毁了,这个指针就是野指针
int main(int argc, const char *argv[]) { int *p=NULL;//undefine *p = 10; printf("%d ",*p); return 0; }
6.指针与函数
//指针变量作为函数参数 //封装一个函数交换两个值 void swap(int a, int b) { int temp; temp = a; a = b; b = temp; return ; } int main(int argc, const char *argv[]) { int a = 10; int b = 20; printf("交换前 a== %d b== %d ", a, b); swap(a, b); printf("交换后 a== %d b== %d ", a, b); return 0; }
问题:
思考下为什么上面的函数值没有交换过来呢
用什么方法能够解决这个问题呢?(值传递,址传递!)
//使用指针变量作为参数 void swap(int *a , int *b) { int temp; temp = *a; *a = *b; *b = temp; return ; } int main(int argc, const char *argv[]) { int a= 10, b= 20; printf("交换前 a== %d b== %d ", a, b); //传递变量的地址 swap(&a, &b); //结果交换过来了! printf("交换后 a== %d b== %d ", a, b); return 0 ; }
7.指针与数组
数组名就是数组的首元素地址,数组名是一个常量
//数组名就是数组的首元素地址,数组名是一个常量 /*int main(int argc, const char *argv[]) { int a[5]={1, 2, 3, 4, 5}; printf("%p ", a); printf("%p ", &a); printf("%p ", &a[0]); return 0; }*/ int main(int argc, const char *argv[]) { int a[5]= {1, 2, 3, 4, 5}; int *p=a;//数组地址赋值给指针变量p for (int i = 0; i<5; i++) { //输出每一个元素 printf("a[%d]==%d ", i,*(p+i)); } return 0; }
//指针实现数组逆序 void func(int *a,int len) { int i; int temp; for (i=0; i<len/2; i++) { //通过指针操作数组元素 temp = *(a+i); *(a+i)=*(a+len-i-1); *(a+len-i-1)=temp; } }
实例:编写一个对整型数组排序的函数
//选择排序法 void sort(int *src, int len) { int i, j, k,temp; for (i = 0; i< len -1; i++) { k = i; for (j= i+1; j<len; j++) { if(*(src+k) > *(src + j)) { k = j; } } if (k!=i) { //通过指针操作数组元素 temp = *(src+k); *(src+k)= *(src+i); *(src+i)= temp; } } } int main(int argc, const char *argv[]) { int a[5]; printf("请输入5个整型数据: "); for (int i= 0; i< 5; i++) { scanf("%d", &a[i]); } //传递数组 sort(a, 5); for (int i= 0; i< 5; i++) { printf("%d ", a[i]); } printf(" "); return 0; }