《C语言入门》
— — 热情像一对翅膀,带我飞过山岭。
前言
指针是C语言区别于其它语言的重要特征,正确灵活的使用指针,能使编写的程序更加简洁、紧凑,提高代码的执行效率。
一、指针是什么
1、指针就是地址,是内存中最小的单元编号。
在生活中,例如:“清华大学6号宿舍楼302房间”就是一个地址,我们可以通过地址找到这个房间。相对应的,在内存单元中也是一样的道理,可以通过一个编号找到指定的内存单元,所以内存单元的编号也称为地址,理解成地址指向内存单元,地址也就形象的称为指针。
综上所述:编号--- 地址 -- 指针是同一个东西。
2、内存单元
内存被划分成若干个小的内存单元,一个内存单元是一个字节。内存单元编号的产生:
当要把编号存储起来的时候就要创建一个变量,也就是 指针变量 。
3、指针大小在 32 位机器上,地址是 32 个 0 或者 1组成二进制序列,1Byte(字节) = 8bit(比特), 地址就得用4 个字节的空间来存储,所 一个指针变量的大小就应该是 4 个字节。在 64位机器上,地址是64 个 0或者1组成二进制序列,1Byte(字节) = 8bit(比特), 地址就得用8 个字节的空间来存储,所 一个指针变量的大小就应该是8 个字节。综上所述: 指针的大小在32位平台是4个字节,在64位平台是8个字节。
4、口语中的‘指针’,通常描述的是指针变量,指针变量是用来存放地址的变量。
#include <stdio.h> int main() { int a = 10;//在内存中开辟大小为4个字节的空间 //*表示pa是个指针变量 int* pa = &a;//将a的4个字节中第一个字节的地址存放在pa变量中,pa就是一个指针变量 *pa = 20;//通过指针变量pa就可以找到存放a的地址 printf("%d",a); return 0; }
综上所述:指针变量是用来存放地址的,地址是唯一标示一个内存单元的。
二、指针类型
1.不同类型的指针解引用
解引用:例:*pa表示解引用操作,*pa通过指针变量pa中存放的地址,找到pa指向的空间。
代码测试:
#include <stdio.h> int main() { int a = 0x11223344; int* pa = &a; *pa = 0; return 0; }
指针变量pa存放这个地址,*pa解引用通过pa中存放的地址,找到pa指向的空间。通过测试发现,int* 的指针的解引用能访问四个字节。
#include <stdio.h> int main() { int a = 0x11223344; char* pa = (char*) &a; *pa = 0; return 0; }
指针变量pa存放这个地址,*pa解引用通过pa中存放的地址,找到pa指向的空间。通过测试发现,char* 的指针解引用只能访问一个字节
“我把张三的家庭地址写在记事本上,不同颜色书皮记事本记录的信息种类不同,有需要的时候去找它。我们可以通过地址找到张三的家。”
指针变量就好像是记事本 ,不同的指针类型,就好比记事本的书皮,不同的书皮意味着记录不同的信息种类,也就是对指针解引用的时候权限不同(能操作几个字节不同)。
综上所述: 指针的类型决定了,对指针解引用的时候有多大的权限(能操作几个字节)。比如: char* 的指针解引用 就只能访问 一个字节 ,而 int* 的指针的解引用 就能访问 四个字节。
2.指针+整数调试
代码和结果如下:
#include <stdio.h>
int main()
{
int a = 10;
int* pa1 = &a;
char* pa2 = (char*) &a;
double* pa3 = (double*) &a;
printf("%p\n",pa1);
printf("%p\n", pa1+1);
printf("-----------------\n");
printf("%p\n", pa2);
printf("%p\n", pa2 + 1);
printf("-----------------\n");
printf("%p\n", pa3);
printf("%p\n", pa3 + 1);
return 0;
}
通过结果发现,pa1 = pa2 = pa3,但是他们+1后的结果却不相同
pa1+1 = ...08
pa2+1 = ...05
pa3+1 = ...0C(c代表12)
得出结论:整型指针+1,跳过一个整型,四个字节 。字符指针+1,跳过一个字符,1个字节。double*指针+1,跳过一个浮点类型,8个字节。
综上所述: 指针的类型决定了指针向前或者向后走一步,步长有多大(距离)。
三、野指针
比如在大街上发现一只非常可爱的小猫,它没有主人,没有家,这时候它就是一只小野猫。指针也是一样。当它指向的位置随机、不正确时就是个野指针。
野指针概念:: 指针指向的位置是不可知的(随机的、不正确的、没有明确限制的)
1、 可能出现野指针的情况
1.1指针变量没有初始化
代码调试:
#include <stdio.h>
int main()
{
int* a;
*a = 10;
return 0;
}
报错:
综上所述: 指针变量没有初始化,这时候它的值默认是随机的,就是野指针
1.2指针越界访问
合法访问:
#include <stdio.h>
int main()
{
int arr[10] = { 0 };
int* p = arr;
int i = 0;
for (i = 0;i<=9;i++)
{
*p = i;
p++;
printf(" %d ",arr[i]);
}
return 0;
}
我们更改更改下循环条件越界访问:
#include <stdio.h>
int main()
{
int arr[10] = { 0 };
int* p = arr;
int i = 0;
for (i = 0;i<= 11;i++)
{
*p = i;
p++;
printf(" %d ",arr[i]);
}
return 0;
}
就会出现这种情况:
综上所述:当指针指向的范围超出数组arr的范围时,p就是野指针。
四、指针运算
1、指针+-整数
在上面已经提到过了,整型指针+1,跳过一个整型,四个字节 。字符指针+1,跳过一个字符,1个字节。double*指针+1,跳过一个浮点类型,8个字节。相减也是一样的。
代码测试:
#include <stdio.h>
int main()
{
int a = 0;
int* p = &a;
*p = *p + 2;
printf("%p\n",p);
printf("%p\n",p + 1);
printf("%p\n",p - 1);
printf("%d",a);
return 0;
}
2、指针-指针
指针-指针 = 两个元素之间的个数。要注意的是,两个指针要指向同一块空间。
代码测试:
#include <stdio.h>
int main()
{
int arr[10] = {1,2,3,4,5,6,7,8,9,10 };
printf("%d", &arr[8] - &arr[0]);
return 0;
}
结果:
总结
初识指针,了解到其实指针就是地址、我们平常口语所讲的指针大多数表示指针变量。指针的类型,什么情况下会出现野指针、指针的运算。收获颇多,继续加油!
接下来继续学习指针和数组、二级指针、指针数组!