浅谈指针的本质

  

内存地址(普通指针)或偏移地址(成员指针)。

指向变量的指针,是数据内存的地址,指向函数的指针是代码内存的地址,指向数据的指针指向数组开始位置的地址。

抽象点说,就是以一种统一的方式产生对不同数据结构的元素的引用

理解指针要注意以下几个点:

  -- 每个指针都有类型,类型决定指针移动时的步长(假设可移动:++ / -- / +n / -n)

  -- 从内容上讲,指针就是地址,尤其是在机器级层面上

  -- 对指针进行类型转换,仅仅是改变了解释指针所指内存区域的方式,位模式没有变

  -- 指针可以指向函数,其值是函数对应机器代码的第一条指令的地址

  -- 指针和数组关系暧昧,如果你明白比例变址寻址,你就能清除数组名,下标,指针类型之间的关系,简单说:数组名即基地址(立即数),下标即变址,指针类型即比例因子,而指针的值就是:偏移量 + 变址 * 比例因子 +基地址【IA32】,这样你就明白数组名是个常量(在机器眼里就是个立即数寻址时对变址没有限制也就说明了C语言对下标越界不检查

  指针是储存地址的一个变量

指针变量储存的就是一个地址, 可以有如下行为:
  * 改变该变量的值;
  * 取得该变量的值
这和其他变量是一样的, 但是指针还可以做到:
  * 改变该变量指向的那个地址的值
  * 取得该变量指向的地址的值
这只是编译器赋予指针的特定行为而已(通过& * 等语法), 在汇编层面大概就是间接寻址了.
因此指针就是储存地址, 纠结「指针的指针」什么的可以退散了.

指针为什么要有类型

汇编中数据是没有类型的, 所以指针的类型是编译器在规定的, 通过了指针的类型检查, 才能保证你少犯错.
因为其他数据有类型, 所以指针也得有类型.


指针的类型表明: 你期望从这个地址里取出来的数据, 是什么类型的.

  大部分时候, 我们想从一个 *int 指针中取出来的值总是 int, 只有在特殊情况下我们才会想把 int 当成 uint 取出来, 类型检查就帮我们减少弄错类型的可能.

  另外, 类型也规定了指针移动的粒度, 你期望从一个 *int 取出一个 int, 那 *(int + 1) 如果是地址+1的话, 不就取出了奇怪的数字?
所以这里的 *(int + 1) 的 1 起始是指代一个 sizeof(int), 这样你才能方便地访问连续的内存数据.
在汇编中大概就是 [arr + 4]. (32位限定), 编译器根据指针的类型帮你做了这一步转换.
 
  你会发现计算机的本质就是计算,计算的内容是什么呢,就是数据,数据哪里来呢,需要有东西搬过来,这里面就需要用到寄存器了,在这里也可以理解成指针,不然计算机里面这么多数据,鬼知道要用到哪些数据来计算呢,要知道运算器只知道计算,再谈指针的类型??不就是告诉运算器或者说是计算机这些数据的内存范围吗,当然也有其他用途。对指针的理解不能止步于此,深入了解还得指望汇编了,无奈暂时没时间学习汇编,暂时粗粗的看看反汇编代码罢了,日后再整理。
 
原文地址:https://www.cnblogs.com/still-smile/p/11646340.html