对于C语言初学者而言,指针部分有点复杂,也有些难理解,可以说是C语言学习之路上的第一道坎,在阅读了不少书籍资料和实验后,决定写下这篇博客,供大家参考。
什么是指针?
指针也是一种变量,存放的是某块内存的地址。
我们知道,内存可以理解为是按字节被分割成若干块的,每一字节都对应着一个编号,并且这些编号从小到大依次排列,这个编号就是它的地址,独一无二,而指针变量中的值就是这些编号
例如如下代码的结果
#include <stdio.h>
#include <Windows.h>
int main()
{
int a = 0;
int *p = &a;
printf("%p", p);
system("pause");
return 0;
}
这就是一个指针变量的内容,一个16进制数,代表着内存中某一个字节的地址
指针解引用和取地址
int *p = &a 这行代码的意思是将变量a的地址赋给了整形指针变量p,
此时p中存放的是a的地址,而p就是对指针进行解引用,p指向p中所存放的地址中的值,即a本身。
对*p进行+1操作,相当于a+1。
&a意思是取a的地址,相当于p
这一块的理解没有难度,但对初学者来说也需要一定时间。
指针的类型
指针的类型很丰富,数据有多少种类型,指针就有多少种类型与之相对,除此之外还有数组指针、函数指针、以及指向指针的指针,即二级指针。
一般来讲,一种类型的指针中所储存的是与之类型相对应的变量的地址。
同时,指针也可以进行强制类型转换操作
int a = 0;
char *p = NULL;
(int *)p = &a;
这里也可以看到,指针的初始化操作是赋值为NULL,表示空指针,指向0地址。
另外,有一种特殊的指针void*,表示不确定类型的指针,可以接受任意类型的指针,常用作函数的参数。
指针的大小
记住!所有指针的大小都一样,与类型无关,只与系统有关,在32位系统下,指针的大小为4个字节,64位系统下,是8字节。
指针的运算
指针作为一种变量是可以进行运算的,
指针加减整数后得到的结果是原地址加上或减去该类型大小的字节数
#include <stdio.h>
#include <Windows.h>
int main()
{
int a = 0;
char *p1 = &a;
short *p2 = &a;
int *p3 = &a;
long *p4 = &a;
double *p5 = &a;
printf("%p\n", p1);
printf("%p\n", p1+1);
printf("%p\n", p2-1);
printf("%p\n", p3+1);
printf("%p\n", p4-1);
printf("%p\n", p5+1);
system("pause");
return 0;
}
上面代码的结果为
如果你对类型的字节大小记得很熟的话,相信你一眼就可以看出指针的一个规律即
指针的类型决定了指针的操作权限(多少字节的范围)
此时你是否有一个疑问,一个int型变量占4个字节,而指针只指向一个字节,那赋值后指针指向的是4个字节中的哪一个呢,答案是4个字节中地址数最低的那一个
也可以称这个最低的地址值是就是int型变量a的地址值。
指针除了加减整数,也可以加减指针,得到的值表示两个变量在内存中存放位置的差值。
二级指针
这时我们应该已经可以得出一个结论,只要是我们所定义的变量,都被储存在内存中,都有一个地址,并可以把它赋给一个指针变量。
那么指针变量也不列外,它也有地址,也同样可以被放在一个指针变量中,而这个指针变量就是我们习惯称之为的“二级指针”。
int main()
{
int a = 0;
int *pa = &a;
int **p = &pa;
return 0;
}
在上面的代码中,二级指针p指向的是用于存放a的地址的指针pa,存放的是pa的地址。
*p等价于pa等价于a。
指针与数组
这是可以说是在C语言学习中,最难啃的一块骨头,我将另开一篇博客陈述。