指针介绍
指针:通过地址能找到所需的变量单元,所以说,地址指向该变量单元。因此,将地址形象的称为“指针”,通过它能找到以它为地址的内存单元
int main() { int a = 10; int *p = &a; printf("%p\n", &a); system("pause"); return 0; }
int* p; 应用变量存储地址(指针标识一块儿内存)
p是一个指针变量,p中存放的地址唯一标示了一块空间 指针-->(变量)地址
内存空间编址:将计算机的内存分成好多小的内存单元,一个内存单元存一个编号,每个编号即为一个地址,这样一个地址标示一块空间
int a = 10; int *p = &a
创建一个变量 int a = 10;——>内存中开辟4个字节的空间,每个字节都有自己的编号。取地址 a : &a ,取的是第一个字节的地址,然后存到 p 里面,称 p 为一个指针变量指针存储:int* p(int* 为 p 的类型, p 因为 int* 而称为指针变量)通常 * 和 p 结合,int 说明 p 指向一个整形,习惯表示成 int *p
32 位机器有 32根地址线,共有 2的32次方个地址,每个地址(内存单元)标示一个字节,就可以给 4G 的空间进行编址在 32(64)位机器上,地址是 32(64)个 0或 1组成的二进制序列,得用 32(64)个 bit位存储,那地址就得用 4(8)个字节的空间来存储,所以一个指针变量的大小是 4(8)个字节
总结:
a>指针是存放地址才出现的,地址是为了标示一块地址空间的
b>指针让地址有地方存放,指针让内存的访问更加方便
c>指针的大小在 32(64)位平台是 4(8)个字节
指针类型
我们都知道,变量有不同的类型,整形,浮点型等,指针也有类型
当有如下代码:
int n = 10; p = &n;
要将&num(num的地址)保存到p中,我们知道 p 就是一个指针变量,那他的类型是怎样的呢?我们得给指针相应的类型
char *pc = NULL; int *pc = NULL; short *pc = NULL; long *pc = NULL; float *pc = NULL; double*pc = NULL;
可以看出,指针是有类型的,指针类型是 : type + * 的方式
char * 类型的指针是为了存放 char 类型变量的地址;
int * 类型的指针是为了存放 int 类型变量的地址;
short * 类型的指针是为了存放 short 类型变量的地址;
long * 类型的指针是为了存放 long 类型变量的地址;
float * 类型的指针是为了存放 float 类型变量的地址;
double*类型的指针是为了存放 double 类型变量的地址。
指针类型意义:
a>决定解引用操作时的访问权限——整形指针解引用,访问了四个字节;字符指针解引用,只访问了一个字节
b>决定指针向前或向后走一步有多大(距离)加减整数的步长 (+1)加的步长——整形指针 +1 —> +4个字节;字符指针 +1 —> +1个字节
指针运算
a> 指针+-整数
b> 指针-指针
c> 指针的关系运算
指针 + -整数#define N_VALUES 5 // 宏定义 float values[N_VALUES]; float *vp; //指针+-整数;指针的相关运算 for (vp = &values[0]; vp < &values[N_VALUES];) { *vp++ = 0; // +1 }
vp = &values[0] —> 初始化(第一个元素地址赋给vp)
N_VALUES] —5 &values[N_VALUES] —> 第6个元素的地址
指针-指针 (得出的是指针与指针之间元素的个数:必须是同类型(同一内存块中进行))
int main() { int arr[10] = { 0 }; printf("%d\n", &arr[9] - &arr[0]); return 0; } system("pause"); return 0; }
代码最终输出结果是: 9
指针的关系运算
初始化为0 (从后往前)
for (vp = &values[N_VALUES]; vp > &values[0];) { *--vp = 0; }
代码简化,这将代码修改如下:
for (vp = &values[N_VALUES-1]; vp >= &values[0]; vp--) { *vp = 0; }
不建议应用这种方法:标准规定,允许指向数组元素的指针与指向数组最后一个元素后面的那个内存位置的指针比较,但是不允许与指向第一个元素之前的那个内存位置的指针进行比较(允许向后越界比较;不允许向前越界比较)