目录
地址
指针
什么是指针?
指针的大小
指针的类型
指针的作用
为什么指针要分类型?
指针运算
野指针
不确定类型指针(void*)
地址
计算机内存每一块存储空间都有一个编号,就像每家每户都有门牌号一样,这个编号就是内存空间的地址,一块内存空间占据的大小是一个字节(8个比特位)
指针 什么是指针?
指针是一种数据类型,就像char int float double这些数据类型一样,也会在内存中占据空间,只不过,指针的作用是用来存储内存空间的地址。
指针的大小
在32位环境下,指针大小为4个字节,在64位环境下,指针大小为8个字节。
指针的类型
- char* 类型
- int* 类型
- float* 类型
- .....
指针的类型有很多,这里只介绍初阶类型
指针类型就是在原有的一些数据类型后面加上* ,例如下面的代码
int main()
{
int* p;
return 0;
}
指针的作用
在上述代码中,p变量就是int* 类型的指针,那么p指针有什么用呢?因为p指针是用来存放地址的,那么我们可以创建一个int 类型的变量num,让p变量来存放num变量的地址。
代码如下:
int main()
{
int* p;
int num = 10;
p = #
return 0;
}
&是取地址 *** 作符,作用是取出num变量的地址,那么我们取出地址放到指针p里面有什么用呢?
我们可以通过p来访问num,可以不直接对num *** 作而改变num。
通俗来讲就是,我现在在一个房间里面放了一个苹果,把门锁了起来,同时,我把钥匙给了小明,那么小明就可以拿着钥匙打开门进入这个房间吃苹果。
这个苹果就是变量num,而小明就是指针p。
举个例子:
#include
int main()
{
int* p;
int num = 10;
p = #
*p = 20;
printf("%d", num);
return 0;
}
*和&互为逆运算,*是解引用 *** 作符,作用就是通过p指针找到num,所以*p和num是等价的,对*p *** 作相当于对num进行 *** 作。
运行结果如下:
为什么指针要分类型?
既然指针的大小不是4个字节就是8个字节,那么为什么要对指针的类型进行这么细致的划分呢?
指针的类型在解引用 *** 作时会体现出用途
例如char* 类型在解引用时只能访问到1个字节,int* 类型解引用时会访问4个字节。
指针运算
- 指针的自增自减,加减整数
指针的自增自减和加减整数会根据指针的类型来约束运算的字节大小。
例如以下代码:
#include
int main()
{
int arr[10] = { 0,1,2,3,4,5,6,7,8,9 };
int* p = arr;
int i = 0;
for (i = 0; i < 10; i++)
{
printf("%d ", *(p + i));
}
return 0;
}
int*解引用时访问4个字节,所以p+1就是p加上4个字节
运行结果如下:
如果我们把int* 改为char* 类型,那么p+1就只能访问到1个字节,再次运行会有怎样的结果呢?代码如下:
#include
int main()
{
int arr[10] = { 0,1,2,3,4,5,6,7,8,9 };
char* p = arr;
int i = 0;
for (i = 0; i < 10; i++)
{
printf("%d ", *(p + i));
}
return 0;
}
运行结果如下:
和之前的运行结果不一样,这就是指针分类型的意义所在,至于为什么第二次的代码会打印出这个结果,后续的博客中会有介绍。
- 两个指针的相减
两个相同类型指针相减会得到这两个指针之间元素的个数,但是要注意只能相同类型指针相减。
有人问,为什么没有指针相加,这就像日期一样,两个日期相减可以得到中间相差的天数,两个日期相加有什么意义?
例如以下代码:
#include
int main()
{
int arr[10] = { 0,1,2,3,4,5,6,7,8,9 };
int* pa = arr;
int* pb = arr + 5;
printf("%d ", pb - pa);
return 0;
}
pa指向首元素,pb指向首元素往后+5,之间隔了0,1,2,3,4,所以相减应该等于5
运行结果如下:
野指针
野指针指的是指针变量中的值是非法的内存地址,野指针指向的内存地址是不可用的,野指针通常会造成非法访问的问题。
举个例子,我在某个酒店定了一个房间,住了一晚上,我告诉小明我在这儿定了个房间,让他明天晚上过来住,但是我第二天早上退房走了,但是小明不知道,他晚上来这个房间,这就是非法访问,因为这个房间的使用权已经不属于我了,酒店已经回收了这个房间。
所以我们创建指针时一般要对指针进行初始化,代码如下:
int main()
{
int* p = NULL;
return 0;
}
NULL 的意思是指向空,但是NULL不等于0,不是一回事。
对于使用完的指针最好将其赋值为NULL.
在编程时,一定要注意野指针,防止非法访问。
不确定类型指针(void*)
- void* 不可以解引用
- void* 可以接受任何类型指针的赋值
任何类型的指针都可以直接赋值给void* 指针,不需要进行强制类型转换,可以理解为void* 包含了其他类型的指针
- void* 可以赋值给其他类型的指针
但是需要强制类型转换,void* 主要用在函数中当作参数来接受其它类型的指针,方便使用
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)