指针详解系列1-指针的定义

指针的描述(以下的所有地方都基于C89标准):
指针与数组,结构,联合等一样也是一种数据对象,其值是另外一个对象的地址(这是重点,指针变量里面保存的内容是另外一个对象的地址)。
“指针”得名于这样的事实:其内容“指向”另外一个对象。指针可以指向任何类型(完整类型的或者不完整类型)的对象。一个指针还可以指向其他指针(也就是指向指针的指针),可以实现“多重间接寻址”。更为重要的是指针还可以指向一个函数(入口地址)。当然,一个指针也可以什么地方也不指向(空指针)。
一个指针并不能指向各种类型的对象(在一定的条件下,可以进行强制类型转换),即并不是各种对象(变量)的地址都可以存储到任一指针对象(变量)中,和其他对象一样,每一个指针对象也有一个确定的类型。说起来好像有点拗口,例如:具有指向字符的指针类型的对象不能用于存储整数对象的地址(即不能把整数对象的地址赋值给指向字符的指针变量,强制类型转换除外),反之亦然。
指针类型是由指向对象的类型确定的,一种指针类型的所有对象(变量)所指向的对象的类型必须是相同的。指针变量在使用之前必须进行说明,其说明的一般形式是:
<指向类型> * <变量标识符>
例如,变量说明:
int *intptr; //一个指向int类型的指针变量intptr
char *charptr; //一个指向char类型的指针变量charptr
char ** ptrtochar;//一个指向char *类型的指针变量ptrtochar

指针变量的长度问题:一个指针变量的取值范围(长度)不是固定的,但是其范围总是应该可以覆盖机器可用内存的地址(这是决定指针变量长度的重点)。比如在一些小RAM的4位机上,可能指针只有11bits,在x86上32bits(也就是早期PC最大内存空间4GB=0xFFFFFFFF的缘故),在64位机上指针就变成了64bits

每一种类型的指针对象都有一个特殊的值NULL。在stddef.h中空指针NULL定义如下
#define NULL 0 /* null pointer constant. */
空指针表示指针不指向任何位置。该值是有别于指向具体对象或者函数的指针的特殊值。
指针的指针变量:是指向另一个指针的地址的一种变量类型。

先看看最基本的,比较单一的,也是常用的指针定义和其在内存的存储内容。
这是我的一段基本测试代码,用来说明指针的最基本原理和用法,虽然只是演示了整数类型的使用,对其他类型具有相同的原理,请举一反三,开发环境基于keil MDK 5.26。

int TestPointer(void)
{
	int value;		//定义一个整型变量
	int result;		//定义一个整型变量
	int *pInt;		//定义一个指向整型类型的指针变量
	int ** ppInt;	//定义一个指针的指针类型的变量
	int *** pppInt;	//定义一个指针的指针的指针类型的变量
	int addr;		

	DebugPrintf("  指针测试:\r\n");
	addr = (int)&value;
	DebugPrintf("value 的地址:0x%08x\r\n",addr);
	addr = (int)&result;
	DebugPrintf("result 的地址:0x%08x\r\n",addr);
	addr = (int)&pInt;
	DebugPrintf("pInt 的地址:0x%08x\r\n",addr);
	addr = (int)&ppInt;	
	DebugPrintf("ppInt 的地址:0x%08x\r\n",addr);

	value = 0x12345678;	//赋值一个整型变量
	pInt = &value;		//指针变量初始化,用value的地址赋值
	result = *pInt;		//通过指针变量pInt取整型变量value的值
	DebugPrintf("result = :0x%08x\r\n",result);


	ppInt = &pInt;		//取指针变量的地址赋值给指针的指针变量
	result = (int)*ppInt;
						//取的是指针变量ppInt的内容(即指针变量pVal的地址)
						//这里使用了一个技巧,强制类型转换。因为*ppInt得到的是一个指针类型变量的值,
						//所以不能直接赋值给整型变量,但是ARM的指针类型和整数类型的数据长度是一样的
						//所以我们把这个地址可以转换为整型数值。
	DebugPrintf("pInt的内容(value的地址) = :0x%08x\r\n",result);
	result = **ppInt;	//通过指针的指针变量ppInt去取整型变量value的值
	DebugPrintf("通过指针的指针**ppInt获取的值 result = :0x%08x\r\n",result);

	pppInt = &ppInt;
	result = (int)*pppInt;	//获取指针的指针的内容(pInt的地址)
	DebugPrintf("通过指针的指针的指针 = :0x%08x\r\n",result);

	return result;
}

指针的基本定义和使用参考代码里面的注释理解。
在这里插入图片描述
我们看看输出的结果,对照代码就比较容易理解。

  1. 前面1-5行分别输出了几个变量在内存中的地址,可以看到,每一个变量占用四个字节,也就是32位长度
  2. 第6行输出了int类型变量result的值。
  3. 第7行显示了一个指针变量的内容,也就是变量result的地址。和前面第1行打印的一致。
  4. 第8行显示了通过指针的指针的变量去访问result的方式。
  5. 第9行展示了一个不常用的,诡异的,匪夷所思的,但是C语言允许而且编译器支持的类型:指针的指针的指针,我们获得了正确的结果。你如果愿意还可以一直定义下去,比如int **** pppInt;一般我们不使用这种晦涩的定义方式,除了耍酷和证明编译器支持以外,平时不要去使用这种难以理解的方式。

原创文章,欢迎转载,请注明来源,未经书面允许,请勿用于商业用途。
在这里插入图片描述

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值