关于指针的认知

指针

指针的概念

内存区的每一个字节都有一个编号,这就是“地址”.如果在程序中定义了一个变量,在对程序进行编译或运行时,系统就会给这个变量分配内存单元,并确定它的内存地址(编号).
– 指针的实质就是内存“地址”.指针就是地址,地址就是指针.
– 指针是内存单元的编号,指针变量是存放地址的变量.
– 指针也是一种数据类型,指针变量也是一种变量.
– 指针变量指向谁,就把谁的地址赋值给指针变量.
– “*”操作符操作的是指针变量指向的内存空间.

需要注意的是&符号可以取得一个变量在内存中的地址,但是不能取寄存器变量.因为寄存器变量不在内存里,而在CPU里面,所以是没有地址的.

指针的大小

指针的大小可以使用sizeof()测得,而sizeof()测得的是指针变量指向存储地址的大小.

不同的平台下的指针,其大小是不同的:
– 在32位平台,所有的指针地址都是32位(4字节).
– 在64位平台,所有的指针地址都是64位(8字节).

空指针和野指针

指针变量也是变量,是变量就可以任意赋值,只要其存储的值不要越界即可(32位为4字节,64位为8字节).但是,当将任意数值赋值给指针变量时,这时的指针就成了野指针,此指针指向的区域是未知(操作系统不允许操作此指针指向的内存区域).所以,野指针并不会直接引发错误.但当操作野指针指向的内存区域才会出问题.

但是,野指针和有效指针变量保存的都是数值,为了标志此指针变量没有指向任何变量(空闲可用),C语言中可以把NULL赋值给此指针,这样就标志此指针为空指针.没有任何指向.而NULL是一个值为0的宏常量.

万能指针 void*

void *指针可以指向任意变量的内存空间.

关于const修饰指针的不同情况

  • 当const修饰指针*时,指针指向内存区域不能修改,指针指向可以修改.
  • 当const修饰变量名时,指针指向不能修改,指针指向的内存可以修改.

数组和指针的关系

数组名字是数组的首元素地址,但它是一个常量.可以用指针间接操作数组.即定义一个变量指向数组的地址.

  • 指针数组,即指针的数组.它是数组,数组中的每个元素都是指针类型.
  • 数组指针,即数组的指针.它是指针,它代表指向一个数组的指针.

多级指针

C语言允许有多级指针存在,在实际的程序中一级指针最常用,其次是二级指针.而二级指针就是指向一个一级指针变量地址的指针.三级指针则是指向二级指针变量地址的指针,以此类推:

即N级指针就是指向N-1级指针变量地址的指针(N>1).

int i = 1;
int *p = &i;  // 一级指针
*p = 10;      // *p就是i,此时i的值已经从1变成10
int **q = &p; // *q就是p, **q就是i
**q = 100;    // **q就是*p也是,值已经从10变成100
int ***t = &q;// *t就是q,**t就是p, ***t就是i
***t = 1000;  // ***t就是**q就是*p也是i,值已经从100变成1000

函数指针

如果在程序中定义了一个函数,则在编译时就会为这个函数代码分配一段存储空间,这段存储空间的首地址称为这个函数的地址,而且函数名表示的就是这个地址.既然是地址就可以定义一个指针变量来存放,这个指针变量就叫作函数指针变量,简称函数指针.

int func(int x);   // 声明一个函数
int (*p) (int x);  // 定义一个函数指针
p = Func;          // 将函数的首地址赋给指针变量p