指针的概述

什么是指针?

  1. 一个内存变量或数组变量在内存中的地址就是指针。
  2. 简单来说,内存地址就是指针,指针就是内存地址
  3. 存放指针(内存地址)的变量就称为指针变量。
  4. 在32位操作系统中,任何类型的指针变量的空间大小都是4个字节。在64位操作系统中,任何类型的指针变量的空间大小都是8个字节。
  5. 指针变量记录的内存地址,也称为他指向的地址。

指针变量的定义方法

格式:变量类型 * 指针变量名称=[ ]
*符号两旁都没有空格或者左边或右边有一个空格都是可以的。
& :取地址,获取一个变量的地址
*:取值

  1. 指针变量自身的大小全部都是4个字节,跟类型毫无关系;
  2. 对目标操作的大小跟类型完全相关;
*p = -1;   //(此处操作4个字节)代替普通变量赋值:i= -1;
*ps = -1;   //(此处操作2个字节)代替普通变量赋值:j= -1;
*pd = 0;    //(此处操作8个字节)代替普通变量赋值:d = 0;
  1. *p等价于是4字节变量i的别名,*ps等价于2字节变量j的别名,
 int a[] = {1,2,3,4,5,6,7,8,9,0};
 int i = -1;
 int *p = a;
 while(++i < _countof(a))
 		printf("%d",*(p+i));  //i:0...8
		
		//p[i]等价于*(p+i) 加1就向高平移1个int,如果是double*的变量加1就平移一个double 
		
  1. 指针变量的步长:
    • 对目标读和写是跟类型相关,double操作8个字节,int操作4个字节;
    • 指针加减也和类型相关,double*的变量加减1跨越一个double的距离,int*cha*同理。
    • 我们把指针变量对目标操作或加减称为步长
  2. 指针变量的赋值原则:
    • 右值必须是指针变量或者指针常量,而不可以是一个整数或者浮点数。例如:
int main(){
		//&n指针常量,p是指针变量
		int n=0,a[20]; //数组可以认为是指针常量
		int *p = 888; //错误, 数值型与地址型不能交互赋值
		int *p = &n;//使用指针常量赋值
		int* q = p; //使用指针变量赋值
		int* p = 0; //正确,经常利用到空地址对指针变量初始化
}

指针变量的等级

指针变量今后分为一级指针和二级以及多级指针变量。

int n = 999;//0级
int *p = &n;//&代表升级,p是一级指针变量;
int ** pp = &p;//&代表升级,p是二级指针变量;
*p = 666;//*代表降级

指针的偏移(加减)

  1. p+n的地址偏移与指针变量的类型有关:
    • xdouble或者int型,偏移的物理距离就是sizeof(x)*n
    • 如果是char*类型,p+n偏移的物理距离是n个字节;
    • 如果是short*类型,p+n偏移的物理距离是n*2个字节;
    • 如果是int*类型,p+n偏移的物理距离是n*4个字节;
    • 如果是double*类型,p+n偏移的物理距离是n*8个字节;
  2. p+np[n]才是等价的,因为p[n]的地址与p指向的地址之间也是相差nsizeof(x)倍;

特殊类型的指针变量

C语言中,特殊类型的指针变量包括:常量指针、指针常量和万能指针等几种类型。

无论是指针常量还是常量指针,const关键字都是编译时禁止修改的意思。只不过一个是禁止修改记录的地址,一个禁止修改指向的内存中的数据。

常量指针

指向常量的指针变量,例如:const int* p;

**常量指针的特点:

  1. 常量指针的核心功能,是阻止修改指针向内存的数值。
  2. 常量指针的特点:禁止对目标数据赋值操作,允许读取操作,允许偏移操作。

指针常量

指针变量中的常量”,例如:int* const p;

**指针常量的特点:

  1. 指针常量:指向固定的位置的指针变量,格式是const在指针变量前星号后。
  2. 禁止偏移操作,允许对数据赋值操作和读取操作。
  3. *pp[0]的类型是int类型,而不是const int类型。
  4. 指针常量必须初始化。

万能指针

只记录地址不记录类型的指针变量,也可称之为“无类型指针”。例如:void* p;

**万能指针的特点:

  1. 定义万能指针的格式为:void* 变量名;
  2. *pp[0]的类型是未知类型,禁止赋值与取值
  3. 禁止对目标数据赋值操作和读取操作,允许指向任何新地址,但禁止自增自减
double d = 10;
p=&d; 	 //编译正确
++p; 	 //编译错误

  1. 如果要对万能指针指向的内存操作,必须先强制转化为一种具体类型。
double *pd = (double*)p;
*pd=9999.9999;

万能指针最常用于做形式参数,功能是对任何类型的实参都可以自动匹配。

测试万能指针

#include<stdio.h>
int main() 
{
	int n = 10;
	double d = 9999.9999;
	char s[]= "abcdefg";
	void *p = NULL;
	p = &n;			//正确:万能指针能接收任何类型的地址
	//*p = -1;		错误:万能指针能皆不能取值也不能赋值
	p = &d;			//正确:万能指针能接收任何类型的地址
	//p[0] = 0;		错误:万能指针能皆不能取值也不能赋值
	p = s;			//正确:万能指针能接收任何类型的地址
	//p++;		错误:万能指针无法加减,因为没有单位长度
	//printf("%d", sizeof(*p));		错误:*p是未知的类型
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值