C语言初识指针

什么是指针?

指针就是编程语言中的一个对象,利用地址,它的值直接指向(points to)存在电脑存储器中另一个地方的值。由于通过地址能找到所需的变量单元,可以说,地址指向该变量单元。因此,将地址形象化的称为“指针”。意思是通过它能找到以它为地址的内存单元
1.听到上面的概念大家可能会有一点不太明白,下面未来说一说这些概念的区别
在这里插入图片描述

我们可以知道,在计算机中所有的数据都存储在存储器中,包括程序的运行。这也就间接的说明了存储器在当代冯.诺依曼计算机体系下存储器的重要性了。下来回到主题。。。。。
一般的话把存储器中的一个字节叫做一个内存单元不同的数据类型占用的内存单元也是不同的。但是为了能正确的访问这些内存单元,那么就要为这些内存单元进行编号,这样每一个内存单元有其相对应编号也就便于查找。这样我们把内存单元的编号叫做地址。既然根据内存单元编号或者是地址就能够找到相应的内存单元,那我们通常也就将地址形象的称作指针。那就可以这样理解:内存单元编号 = 地址
但是请注意:内存单元的指针和内存单元的内容完全是两个不同的概念。我们通过指针找到对应的内存单元从而获取内存单元中的内容,对于一个内存单元来说,单元的地址即为指针,其中存放的数据才是该单元的内容;
指针就是变量,用来存放某个变量地址的变量。C语言规定所有变量在使用前必须先定义,指定其类型,并按此分配内存单元。指针变量不同于整型变量和其他类型的变量,他是专门来存储地址的,所以必须将他定义为“指针类型”
在C语言中,允许用一个变量来存放指针,这种变量就叫做
指针变量
。一个指针变量的值就是某个内存单元的地址或称为某内存单元的指针
这样相比大家就能理解这些容易混淆的概念了!!!

那么问题来了,一个指针到底的有多大?并且内存单元是如何编址的?

对于32位机器,有32根地址线,每一根地址线在寻址是产生一个电信号正电/负电,那么32根地址线就会产生2^32个不同地地址;
00000000 00000000 00000000 00000000
00000000 00000000 00000000 00000001

11111111 11111111 11111111 11111111
而且每一根地址表示一个内存单元,这样就可以给:
(2^32Byte == 2^32/1024KB ==232/1024/1024MB==232/1024/1024/1024GB == 4GB)4GB的存储空间进行编址。同样的64位机器侠编址方式也是相同的;
这样也就可知:
1、32位下地址由32个比特位组成的二进制序列,那么存储地址就需要4字节空间,所以一个指针变量的大小就应该是4字节;
2、同理可知64位下,一个指针变量大小为8字节;

来一段代码体会一下:
在这里插入图片描述

指针和指针的类型

变量有不同的类型,整形、字符型等待;那么指针是否有类型呢?答案是:,为什么我们来看看:

int num = 10;
p = #//这句是否正确?在编译器中会报错,因为p作为一个指针变量,缺少类型

//指针的类:
har *pc = NULL;
int *pi = NULL;
short *ps = NULL;
long *pl = NULL;
float *pf = NULL;
double *pd = NULL;

可以发现:指针的定义方式是: type + * + 变量名
从上可以看出来,指针指向那种类型的变量的地址,那么指针的类型就是该变量的类型;
既然指针类型存在,那么意义是做什么?
这里的作用一个就是指针运算当中指针加减整数和指针解引用这两方面。
指针 ± 整数:
在这里插入图片描述可以看出来,指针的类型决定了指针向前或者是向后走一步有多大的距离;

指针解引用:
在这里插入图片描述
指针的类型决定了,对指针解引用的时候有多大的权限(能操作几个字节)。 比如: char* 的指针解引用就只能访问一个字节,而 int* 的指针的解引用就能访问四个字节。
指针和数组名:
在这里插入图片描述
我们知道在内存中数组的存储是连续的。那么我们以此类推可知数组名 = 数组首元素地址 = 数组的地址

指针运算

(1)算数运算:只两种形式形式

指针± 整数: 数组在内存中数连续存储的,后面的元素地址肯定大于前面的元素地址,+1就是指针向后移动一个元素,-1就是向前移动一个元素;对整数进行扩展保证对指针执行加法运算能产生相同的结果,而不管数组的长度是多少;我们可知当对指针执行加减法时,如果指针停在了数组第一个元素前一位时,那么这种行为是未定义的视为非法,但是停在最后一个元素后面确实合法的,但是如果对该位置进行间接访问(解引用)可能会失败;

#define SIZE 5
int arr[SIZE];
int *pi;
for(vp = arr;arr<&arr[SIZE];){
	*vp++ = 0;
}

上面函数功能将一个数组初始化为0;
在这里插入图片描述
注意:循环结束的条件就是arr[SIZE],此时vp位置处于数组最后一个元素的下一位,前面说过这个位置虽然是合法的,但是间接访问可能访问到原先存储于这个位置的变量,因为这个位置是位置不确定的。所以我们一般不执行解引用;
指针 - 指针:
注意:这样做的前提就是两个指针都指向同一个数组中的元素时,才允许指针相减。
在这里插入图片描述
当两个指针相减的结果类型是ptrdiff_t,是一种有符号整数类型。其结果是两个指针在内存中的距离(距离以数组元素的长度为单位,而不是以字节为单位),因为减法运算的结果最后将除以数组元素类型的长度;相当于如果p1指向arr[1]而p2指向arr[2],那么p2-p1将相当于j - i;不论数组包含的元素类型如何,指针运算结果都是不变的;

**(2)关系运算:< 、<= 、> 、>= **
注意:这样做的前提就是两个指针都指向同一个数组中的元素时,才允许指针相比较。
根据操作符的不同表达式会将那个指针指向数组中更前或更后的元素。但是如果是两个任意元素进行比较那后果是未知的,也是毫无意义的,这和避编译器选择存储数据的位置有关。 但是可以对任意的两个指针执行相等或者是不相等的比较,因为这种结果和编译器选择在何处存储数据无关----指针要么指向同一个地址,要么指向不同的地址

for(vp = &arr[SIZE];arr>arr;){
	*--vp = 0;
}
//将数组的元素以相反的次序清除

首先两个指针执行指向同一个数组,让指针vp指向数组最后一个元素的后一个位置,先执行自减操作在执行解引用操作,,
但是还有一种操作就是:

for(vp = &arr[SIZE-1];arr>=arr;vp--){
	*vp = 0;
}

会报错!因为c规定:允许指向数组元素的指针与指向数组最后一个元素后面的那个内存位置的指针记相互比较,但是不允许与指向数组第一个元素的前一位内存位置的指针想比较。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值