详解 万恶之源——指针(1)

对于学C的人来说,指针应该是很多人噩梦的开始。刚开始时可能还能听懂,到后面就什么不会了。指针是后面学习的基础,所以学好指针十分关键。

一.内存、地址、指针

地址指的就是内存中某一单元的编号。就像楼房的门牌号一样,可以通过门牌号定位到某个房间,我们可以通过地址定位到内存的一个地方。指针是什么呢?指针可以理解成地址,通过指针也可以定位到内存中的某一个单元。指针的作用就是访问内存。

二.指针变量

1.取地址符(&)

取地址符是&,可不要与&&弄混。取地址符,顾名思义,就是取出地址的符号。如我们定义了一个int变量a,然后取地址a,(&a),这样我们就可以得到a在内存上所占4个字节空间的第一个字节的地址了(int变量占4个字节)。

2.指针变量定义

指针变量的定义格式:

int a=10;
int* p=&a;

类型+*+变量名

指针变量存储的是地址,像上面的代码,p存储的是a在内存上的地址。

注意:指针变量本身也是一个变量,也会在内存上开辟空间来储存地址,因此指针变量也有地址,这就有了指向指针的指针,就是再定义一个指针变量来储存指针变量p的地址。

3.解引用操作符(*)

定义完之后,我们可以使用解引用符来将解引用指针变量,取出它所储存的地址里的值。

int a=10;
int* p=&a;
int c=*p    //解引用p后,c就等于10
4.指针变量的大小

char* 、int* 、double* 、short*等,在相同的环境下所有的指针变量的大小是相等的,在32位是4个字节,在64位是8个字节。

5.指针变量类型的意义

char*类型的指针变量每次可访问1个字节,short*类型的指针变量每次可访问2个字节,int*类型的指针变量每次可访问4个字节。

由此我们可以进行下面的内容,指针变量加减整数。

p+1(p是int*类型)就是在一开始的地址往后跳4个字节,相同的是如果是char*那么就往后跳1个字节。

6.void*类型

void*是一种特殊的指针变量类型,没有具体的类型,又叫泛型指针,可以接受任何类型变量的地址。当然,它的缺点也很明显,不能解引用,不能进行与整数相加减,无法进行指针的运算。

三.野指针

野指针就是指向位置不可知的指针。

1.成因

(1).指针未初始化,让指针随机指向了内存空间的某一地址;

(2).指针越界访问,比如我们定义了一个数组有10个变量,结果我们操作后让指针指向了第11个数,这时就会发生指针的越界访问,非法访问内存;

(3).指针指向的空间释放,这种问题一般出现在有函数调用的代码里,在前面的文章中有介绍函数栈帧的创建和销毁(如果大家感兴趣的话可以去看一下),可知,在函数调用完之后,调用函数开辟的空间会被释放,如果我们返回了函数内定义的一个变量的地址,那么空间释放后该空间的内容早已不是储存时的内容,因此会非法访问内存。

2.规避

预防野指针的出现,我们一定用注意好上面的3个原因。如果定义一个指针变量,可以让其先指向空,即NULL。

四.assert断言

在<assert.h>的头文件里定义了一个函数assert(),用以用以确保程序符合某一条件,如果不符合就终止运行,同时返回出错的文件名和代码的行号。如果程序不再需要assert无需一个一个全部删掉,只需在<assert.h>的头文件前加上#define NDEBUG就可关掉全部assert,十分方便。当然缺点也有,增加程序的运行时间。

五.传址调用

顾名思义,就是传入地址以便使用。

void swapp(int* x,int* y)
{
	int t;
	t = *x;
	*x = *y;
	*y = t;
}
int main()
{
	int a=1, b=2;
	int* pa = &a;
	int* pb = &b;
	swapp(pa,pb);
	printf("%d %d", a, b);
	return 0;
}

互换值就是经典的传址调用的例子。

如果我们只是简单传入a和b的值,函数调用传入的值只是在空间上赋值了a和b的值,形参的改变不会影响实参的变化。但是如果我们传入的是地址,那么直接取地址就是在原来a和b的内存空间单元上修改,因此可以完成值交换的功能。

如果我们编写程序时要对实参做一些操作,要选择传址调用。

以上就是全部内容了,创造不易,如果喜欢的话点个赞点个关注^-^

谢谢大家^_^

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值