- 指针是什么
- 指针和指针类型
- 野指针
- 指针运算
- 指针和数组
- 二级指针
- 指针数组
一.指针是什么
指针是编程语言中的一个对象,利用地址,它的值直接指向存在电脑存储器中另一个地方的值。将地址称为指针,即通过它能找到以他为地址的内存单元
注: 内存单元的编号,内存单元的地址 和 指针是一个东西
指针就是地址,也是一个变量,用来存放地址的变量
一个内存单元的大小是一个字节,当给其一个编号就是地址
int main()
{
int a = 10;//a占4个字节
int *pa = &a;//拿到的是a的第一个字节的地址
//pa就是一个指针变量
*pa = 20;
}
注意:指针的大小在32位平台是4个字节,64平台是8个字节
二.指针和指针类型
1.指针大小
#include <stdio.h>
int main()
{
char* pa;
short* pc;
float* pe;
printf("%d\n", sizeof(pa));
printf("%d\n", sizeof(pc));
printf("%d\n", sizeof(pe));
return 0;
}
//4 4 4
注意:不管是什么类型的变量,在32位平台大小都是4个字节,64为平台都是8个字节
2.指针类型的意义
(1)指针+-整数
#include <stdio.h>
int main()
{
int a = 0x11223344;
int *pa = &a;//内存中:44332211
*pa = 0;//经过调试查看内存可知,内存中变成 00000000
//char *pa = &a;
//*pa = 0;//经过调试查看内存可知,内存中变成 00332211,后面未变0
return 0;
}
//可知指针类型的不同影响不同
可以看到p和p+1的地址相差4,而pb和pb+1相差1.
可以看到p和p+2的地址相差8,而pb和pb+2相差2.
总结: 指针类型的不同,操纵地址的增减能力是不同的
指针走一步,能走多远
(2).指针的解引用
下图中展示了内存中char*类型的解引用进行1个字节的1的赋予
下图中展示了内存中int*类型的解引用进行4个字节的1的赋予
指针类型决定了 指针解引用的权限有多大(能操作几个字节)
三.野指针
(1)概念:指指针指向的位置是不可知的(随机的,不正确的,没有明确限制的)
(2)成因:
1.指针未初始化
#include<stdio.h>
int main()
{
int *p;//p是一个局部的指针变量,局部变量不初始化的话,默认是一个随机值
*p = 10;//访问的地址不知道是不是自己的,造成非法访问内存了
return 0;
}
2.指针越界访问
#include<stdio.h>
int main()
{
int arr[10] = { 0 };
int *p = arr;
int i = 0;
for(i=0;i<=10;i++)//判断为i<=10时会超出范围造成越界
{
*p = i;
p++;
}
return 0;
}
3.指针指向的空间释放
#include<stdio.h>
int* test()
{
int a = 10;
return &a;
}//当返回后,a的地址就已经返回给操作系统了
//但返回后程序会记住这个地址,但已经不属于我们了,此时访问是非法的
int main()
{
int*p = test();//导致野指针的出现
*p = 20;
return 0;
}
注意:如何规避野指针
1.指针初始化 2.小心指针越界 3.指针指向空间释放及时 置NULL
4.指针使用之前检查有效性
int main()
{
//当不知道要给p初始化什么值时,直接初始化为NULL
int *p = NULL;
//c语言本身是不会检查数据的越界行为的
//指针使用之前检查有效性
int *p = NULL
*p = 10;//访问NULL时,这个地址是不属于我们的
return 0;
}
四.指针运算
1.指针+-整数
#include<stdio.h>
#define N_VALUES 5
int main()
{
float values[N_VALUES];
float* vp;
//指针+-整数;指针的关系运算
for (vp = &values[0]; vp < &values[N_VALUES];)//指针的关系运算
{
*vp++ = 0;
}
return 0;
}
2.指针-指针(得到的是两个指针之间的元素个数)
前提:两个指针指向同一块空间
#include<stdio.h>
int main()
{
int arr[10] = {1,2,3,4,5,6,7,8,9,10};
printf("%d\n",&arr[9]-&arr[0]);
//char b[5];
//printf("%d\n",&arr[9]-&b[0]);//这种是错误的
//两个指针相减必须指向同一块空间
}
//结果:9
应用:计算字符串长度
#include<stdio.h>
#include <string.h>
int my_strlen(char* str)
{
char* start = str;
while (*str != '\0')
{
str++;
}
return str - start;//指针-指针
}
int main()
{
int len = my_strlen("hxdlq");
printf("%d\n", len);
return 0;
}
注意:指针+指针是无意义的
3.指针的关系运算
//与后比
for(vp = &values[N_VALUES]; vp > &values[0];)
{
*--vp = 0;
}
//与前比
for(vp = &values[N_VALUES-1]; vp >= &values[0];vp--) {
*vp = 0; }
C语言中标准规定指向数组元素的指针与后面的想比,不能与前面的比较
五.指针与数组
数组名是数组首元素的地址
六.二级指针
#include<stdio.h>
int main()
{
int a = 0;
int* pa = &a;//pa是指针变量,一级指针
int** ppa = &pa;//二级指针,存放指针变量的地址
//pa也是个变量,&pa是取出存在pa中的地址
printf("%d",**ppa);
return 0;
}
七.指针数组
#include<stdio.h>
int main()
{
int arr[10];//整形数组
char ch[7];//字符数组
//指针数组——存放指针的数组
int* parr[5];//整形指针数组
char* pch[5];//字符指针数组
return 0;
}