1.什么是地址: 我们说变量都有自己的地址, 计算机要找到某个变量,必须知道该变量的地址.我们可以通过 & 获得变量地址
取地址符 : & 通过取地址符就能把变量的地址给取出来.
int main(int argc, const char * argv[])
{
int a;
printf("%p\n", &a);//输出变量a的地址
return 0;
}
2.什么是指针?
假如我们拥有很多客户的地址, 那么我们需要一个通讯录来保存这些客户的地址, 同样对于计算机来说, 也需要用一个工具来保存变量的地址, 那么这个工具,就是指针
指针就是用来保存内存地址的变量,本质是变量,变量存放的是地址,指针变量同样具有变量名,变量类型,变量值
我们可以通过图形来表示
指针定义:
一般形式: 类型 * 标示符
标示符: 表示指针变量的名字
类型: 表示指针指向的数据类型
int main(int argc, const char *argv[])
{
int a;
int *p;// 定义一个指针类型的变量p
p= &a;//取出a的地址赋值给指针p
printf("%p\n", p);
printf("%p\n", &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\n", *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\n", *(int *)p);
printf("%c\n",*(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\n",*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\n", a, b);
swap(a, b);
printf("交换后 a== %d b== %d\n", 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\n", a, b);
//传递变量的地址
swap(&a, &b);
//结果交换过来了!
printf("交换后 a== %d b== %d\n", a, b);
return 0 ;
}
7.指针与数组
数组名就是数组的首元素地址,数组名是一个常量
//数组名就是数组的首元素地址,数组名是一个常量
/*int main(int argc, const char *argv[])
{
int a[5]={1, 2, 3, 4, 5};
printf("%p\n", a);
printf("%p\n", &a);
printf("%p\n", &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\n", 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个整型数据: \n");
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("\n");
return 0;
}