目录
一、由一个函数问题引出指针
首先,在我们学习指针之前有一个小小的问题需要我们去思考一下,就是我们如何在一个函数的内部改变一个变量的值。我们尝试用之前的知识写出如下代码。
#include<stdio.h>
void exchanger_num(int a,int b)//设形参a,b
{
int tem = 0;
tem = a;
a = b;
b = tem;
}
int main()
{
int a = 0, b = 5;
exchanger_num(a, b);//通过函数实现两个数交换
printf("%d", a);
printf("%d", b);
return 0;
}
运行后发现我们的a和b的值并没有发生交换,于是我们大为震惊,为了研究方便我将函数里的a,b的名称换掉,观察他们的变量特性。
在调试过程中发现a和b的值根本就没有变化,而变化只是num1,num2,我们发现通过取地址操作符发现对应变量的地址都不相同,这是应为num1,num2他们只是拷贝了a和b的值而创建的新变量我们对这种操作叫做值传递。让我们暂时将这个问题放到一边,我们需要首先搞明白什么是指针才能解决这个问题。
二、指针的意义
一个变量在创建的同时,它需要一个开辟一个空间去保存赋给它的数值,就需要占据一个空间,但如果一个在工程中有无数个变量存在时,我们就需要一个能快速定位我们所需变量的工具----指针。顾名思义就是指向某一个变量的东西。可以理解为指向变量的地址。ok,指针的概念我们大概了解了,呢我们就通过解决上面的问题来进一步学习它。
#include<stdio.h>
void exchanger_num(int* p1,int* p2)
{
int tem = 0;
tem = *p1;
*p1 = *p2;
*p2 = tem;
}
int main()
{
int a = 0, b = 5;
//&a就是表示找到a的地址
//*pa就是代表从pa的地址来找到a
int* pa = &a;
int* pb = &b;
exchanger_num(pa, pb);//通过函数实现两个数交换
printf("%d\n", a);
printf("%d\n", b);
return 0;
}
我们将程序改写,运行后
发现a和b确实发现交换了值,我们通过了两个指针变量完成了这个操作,我们通过a和b的地址找到a和b的变量空间并对它们的值进行了交换。
三、指针变量
int a = 10;
char ch = 'l';
double b = 20.0;
int* pa = &a;
char* pch = &ch;
double* pb = &b;
形如tybe*的变量都是指针变量它存放就是对应变量的地址。我们就可以通过解引用操作符来找到变量的地址也可以将指正变量传递给函数让函数能对变量进行操作。
四、指针变量类型的意义
我们可以通过类型名可以大概对指针类型有个初步的认识
int* a//代表a是指向int型的指针变量
char* ch//代表就是一个指向char型的指针变量
但这样仅仅只是一个很粗浅的认识了,我们先来写一段代码
#include<stdio.h>
int main()
{
int a = 0x11223344;
int* pa = &a;
*pa = 0;
printf("%d",a);
}
这是a的内存空间,经过pa操作后
确实按我们的预期改变
#include<stdio.h>
int main()
{
int a = 0x11223344;
/*int* pa = &a;
*pa = 0;*/
char* pa = &a;
*pa = 0;
printf("%d",a);
}
但如果我们设一个char型的指针变量去改变a的值呢?编译器似乎没有找到什么问题
我们会发现,只有一部分被赋值为了0
所以我们就会发现:
1.指针类型代表了指针的步长,是它每一次加1后增加的字节数。
2.指针类型也决定了每次解引用操作后一次性访问几个字节的大小。
总而言之,指针类型就是对内存的不同字节大小的视角访问。
四、野指针
野指针就是没有指向一个明确变量的指针,就像一个没有初始化的变量一样,在程序中是非常危险的,呢么我们该怎样规避野指针的出现呢?
1.野指针产生的原因:
如果我们创建了一个指针,但没有具体给指针变量明确的变量地址,这样一个野指针就产生了。
int* pa;
*pa=?
又或者是数组访问越界的时候出现
int arr[10]={1,2,3,4,5,6,7,8,9,0}
for(i=0;i<=10;i++)
{
printf("%d",arr[i]);
}
数组中有10个元素,但我们却访问数组11次,呢最后一个指针访问的变量就是没有产生的,而这个指针也就称为野指针。
再有可能出现野指针的情况就是用于访问函数中创建的变量时,而在其他函数中再次访问,由变量的生命周期决定了函数变量已经被销毁所以访问它的指针就没有了指向意义。
当我们明白了这些野指针的出现原因后我们就可以在平时的使用中防范它的出现。
五、指针运算
1.指针之间关系的比较
int arr[5]={1,2,3,4,5};
for(int i=0;arr[i]<arr[5];i++)
{
printf("%d",arr[i]);
}
在数组中数组中元素是按由低到高的地址存放的我们可以通过比较地址之间的大小关系完成指针的运算
2.指针-指针
注意:两个指针必须指向的是同一个空间。
得到的是两个指针绝对值之间的元素个数。
六、二级指针
二级指针一句简单的话就是指针变量的地址。
int a=10;
int* pa=&a;
int* *pa=&pa;//这就是二级指针
很简单的一个概念希望大家不要觉得它很难理解哈。
七、指针数组
就是将一个数组的元素的指针作为元素的数组。这里要注意一下和数组不一样,指针数组的元素不一定连续。
上面的概念还是有点不合适,但是核心的意思就是将数组的地址存入指针数组中,下面我再来举一个例子来方便大家的理解。
#include<stdio.h>
int main()//用指针数组实现二维数组
{
int a[] = { 1,2,3 };
int b[] = { 4,5,6 };
int c[] = { 7,8,9 };
int* arr[3] = { a,b,c };
for(int i=0;i<3;i++)
{
for(int j=0;j<3;j++)
{
printf("%d ", arr[i][j]);
}
printf("\n");
}
return 0;
}
- ok,这就是我对指针的初步认识,如有不足请各位大佬指点,感谢。