指针的定义
内存编号---地址---指针
指针是一个宏观的概念:包含指针(地址)与指针变量
指针是一个地址,指针变量是存放地址的一个变量(称之为变量的原因是:在指针变量中存放的地址是可以更改的)
在内存中一个地址大小为一个字节,但是指针大小是有4字节的,所以指针指向的是这个变量地址的首地址
一个指针变量指向的是某个地址,是16进制,其中8位数,但是0x11223344其中每两位代表一个字节(注:一个字节表示8个比特位,四个比特位能够计算的最大值是15,进而可以表示16进制)
指针类型的意义
1、决定其访问的是几个字节(解引用权限):int 类型访问的是4个字节,char 访问的是1个字节
2、决定了指针加一,到底是跳过了几个字节;(步长)
int main()
{
int arr[10] = { 0 };
char* p = arr;
//因为这里是char 类型所以在下面循环+1的时候,跳过的是1个字节
//如果这里是int 类型,那么加一跳过的就是4个字节
int i = 0;
for (i = 0;i < 10;i++)
{
*(p + 1) = 1;
}
return 0;
}
int main()
{
char arr[10] = { 0 };
char* p = arr;
printf("%d\n", p);
printf("%d\n", p+1);//这里跳过的就是1个字节即1个地址
int* pc = arr;
printf("%d\n", pc);
printf("%d\n", pc+1);//这里跳过的就是4个字节即4个地址
return 0;
}
野指针
造成方式
int main()
{
////未初始化的指针就是野指针:即没有规定指向哪里的指针就是野指针
//int* p;
//*p = 20;//这里的p就是野指针
//越界访问造成野指针
//int arr[10] = { 0 },i;
//int* p = arr;
//for (i = 0;i <= 10;i++)
//{
// p[i] = 1;//这里的下标i到达10,越过最大下标9,造成越界,形成空指针
//}
return 0;
}
void* text()
{
int a = 0;
return &a;
//在return之后这个程序就完成了,里面任何的变量的地址都会被释放重新归还给系统
}
int main()
{
int* p = 0;
*p= text();//这里使用的是已经被释放的地址,即p形成了野指针
printf("%d ", p);
return 0;
}
避免野指针出现的四种方法:
1、指针初始化
2、避免越界
3、指针指向空间释放及时的使用空指针NULL
4、在使用指针之前使用判断if如果是有效指针就可以使用
int main()
{
int* p =NULL;//再把指针使用完成之后就把指针置成空指针
if (p != NULL)//空指针无法使用,与野指针几乎相同,只是并没有指向的目标
*p = 2;//这样的判断可以尽可能避免野指针的出现
return 0;
}
指针运算
指针的关系运算
int main()
{
int arr[10] = { 0 };
int* p = 0;
for (p = arr[0]; p <= arr[9];)//这里的p <= arr[9]是指针的关系运算,程序是从低指针向高指针进行运算
{
*p++=0;//这里是指针加减整数的运算,跳到下一个地址
}
return 0;
}
指针与指针进行运算
int main()
{
int a[10] = { 0,1,2,3,4,5,6,7,8,9 };
char b[10] = { 0 };
int c = &a[9] - &a[0];
//这里的结果是定义的数组的下标的差值,差了多少的类型大小的值
int d = &a[10] - &b[0];
//这里其实上是错误的,两种数组不在同一地区里,无法进行计算:如果分配到不同的地区,那么两个数组首地址之间的个数将无从检查
printf("%d ", d);
printf("%d ", c);
return 0;
}`
指针规定:
允许数组指针指向数组后面的一个地址与前面进行比较,但是不允许数组指针直线数组前面的一个地址与后面的进行比较
指针的特殊写法
int main()
{
int arr[10] = { 0,1,2,3,4,5,6,7,8,9 };
int* p = arr;
printf("%d\n", arr[2]);//这里的[]本质上是一个操作符,它与+-并没有区别
printf("%d\n", 2[arr]);//所以既然能够a+b=b+a,那么这种arr与2进行交换一是可以的
printf("%d\n", p[2]);//他们最终翻译成*(p+2);
printf("%d\n", 2[p]);
return 0;
}
多重指针
int main()
{
int arr = 1;
int* pa = &arr;
int** ppa = &pa;
int*** pppa = &ppa;
//int*或者int**是等于号右面的类型而*pa是pa的类型
return 0;
}
指针数组
int main()
{
int arr[10] = { 0 };//数组:一个存放数字的数组
char ch[5] = { 0 };//字符数组:一个存放字符的数组
int* parr[10] = { 0 };//指针数组:一个存放int 类型指针的数组
char* pch[5] = { 0 };//指针字符数组:一个存放char 类型指针的数组
return 0;
}