当前位置:主页 > 生活知识 >

c语言指针(C语言的指针不是地址吗?为什么地址

  • 生活知识
  • 2023-09-10 09:19
  • 来源:www.renliuw.cn
  • 生活知识

谢谢邀请。

题主的疑问应该是,C语言的指针变量里存放的是地址,而地址明明是一个整数,为什么整数还要区分类型?至于指针的加法,题主应该是注意到了有时候 1+1 并不等于 2,对不?其实这并没有什么难的,请继续往下看。

为何要有不同类型的指针变量

稍稍思考一下,应该能够发现,C语言中的指针是通过修改内存来修改变量的值的

既然指针是通过修改内存来修改变量的值的,那么,一个指针一次修改多少内存呢这就涉及到指针的类型了。请看例子,相关C语言代码如下

对于数组 i[8],i 其实就表示这个数组的首地址,所以可以直接把它赋值给指针变量 p1。这样一来,我们就可以通过 p1 来修改数组 i 了。

指针 p1 是 signed char 类型的,通过 p1 修改 i 所在内存时,一次修改 sizeof(signed char) 字节,也即 1 字节。那么,p1+1 指向的就是 i 的第二个元素(i[1]),执行 (p1+1) = 5; 以后,i[1] 就等于 5 了。

按照这个逻辑,p2 是 int 类型的指针变量,请看上图,通过 p2 访问数组 i 时,一次访问的实际上是 sizeof(int) = 4 字节内存。所以 (p2+1) = 9; 实际上修改的是 i 的第 5~8 字节。

我们把C语言代码写完整些,通过 p1 修改后,把 i 全部打印出来;通过 p2 修改后,再把 i 全部打印出来,请看如下C语言代码

编译并执行这段C语言代码,得到如下输出

1 5 3 4 5 6 7 8
1 5 3 4 9 0 0 0

指针的加法

看到这里,你可能会有疑问了,i 的地址为 4000,那 p1 和 p2 指向的也是 4000,p1+1 指向 4001 地址,这没什么好说的。 p2+1 指向的却是 4004? 4000+1 等于 4004 ,这不是扯淡吗?!

这还真不是扯淡,题主可以看看我之前关于C语言数据类型的问答或者文章,应该能够注意“+”运算符要求两边的操作数是同一类型的,如果不同则会自动转换。

p1 和 p2 是指针类型的,而 “+1” 的这个“1”是整型的,在做加法之前,会有自动数据类型转换的过程。p1 是 signed char 型的指针变量,所以“+1”就相当于“+1 x sizeof(signed char)”, p1+1 = 4001。类似的,p2 加上整型 1 就相当于“+ 1 x sizeof(int)”, p2+1=4004。

为了验证我们的分析,下面写C语言代码做实验,我们分别定义 signed char 型的指针变量 p1 和 int 型的指针变量 p2,均赋值为 1,然后分别对 p1 和 p2 加一,打印它们原来的值,和加一后的值,请看如下C语言代码

编译并执行这段C语言代码,得到如下输出

p1=0x1, p1+1=0x2
p2=0x1, p2+1=0x5

这就验证了我们的分析。类似的,读者可以自行分析 long 、float 、double 等任意类型的指针变量的加法运算。

可以将指针的加数“1”看作有“单位”的,单位大小取决于指针的类型。这样就好理解 “1+1”不等于 2 的情况了,因为 1千克 + 1毫克 不等于 2 千克,对不?

作为延伸,下面再讨论一些C语言指针的特性。

指针变量占多少内存空间?

既然指针变量存储的是内存地址,那么指针变量的位宽就应该保证能够存储最大的地址。例如在大多数 32 位计算机中,指针变量的位宽为 4 字节,因为多数情况下,在 32 位计算机中,最大的内存地址为 0xffffffff,至少需要 4 字节才能完整保存。相应的,在大多数 64 位计算机中,指针变量的位宽为 8 字节。

指针这么强,能操作任意地址码?

很多程序员都说,某类型的变量,一定不能用其他类型的指针操作。这句话其实并不严谨,例如上面举的例子中的 char 类型数组 i[8],我们完全可以使用 int p2 指针把它当做两个 int 型变量使用。

只不过一定要小心 p2 别超过 i[8] 的范围了,p2+2 指向的就是数组 i 后的地址了。这里可能存储着非常重要的信息,如果使用 p2+2 把这部分的内容修改了,程序出现段错误退出还好,要是没有报错,却给出了错误结果就麻烦了,这种错误非常难发现,所以在开发阶段就应该小心处理。

按照上面的分析,在定义局部指针变量时,如果忘了对它初始化,局部变量的值是任意的,这也就是说它可能指向任意地方,这时如果使用它,也有可能出现难以发现的错误。

这种指向不确定地址的指针,程序员习惯称为“野指针”。

为了避免出现野指针,在定义指针变量时就应该给它明确的初值,例如

就是把地址0转换成指针类型,称为空指针,它的特殊之处在于,操作系统不会把任何数据保存在地址0及其附近,也不会把地址0~0xfff的页面映射到物理内存,所以任何对地址0的访问都会立刻导致段错误。 p = 0;会导致段错误,就像放在眼前的炸弹一样很容易找到,相比之下,野指针的错误就像埋下地雷一样,更难发现和排除,这次走过去没事,下次走过去就有事。

void 指针常常被称作万能指针,限于篇幅,以后再讨论。

欢迎在评论区一起讨论,质疑。文章都是手打原创,每天最浅显的介绍C语言,喜欢我的文章就关注一波吧,可以看到最新更新和之前的文章哦。

无痛人流