指针
1.指针是什么
指针是内存中一个最小单元的编号,也就是地址
指针变量是用来存放内存地址的变量
本质上指针就是地址
指针变量大小是4个字节
type+*
#include<stdio.h>
int main()
{
int a = 10;
int* p = &a;
return 0;
}
2.指针和指针类型
(1)指针+整数
指针类型决定了指针在被解引用的时候访问几个字节
int* 4个字节
char* 1个字节
#include<stdio.h>
int main()
{
char* pc = NULL;
short* ps = NULL;
int* pi = NULL;
double* pd = NULL;
//sizeof 返回的值的类型是无符号整型 unsigned int
printf("%zu\n", sizeof(pc));
printf("%zu\n", sizeof(ps));
printf("%zu\n", sizeof(pi));
printf("%zu\n", sizeof(pd));
return 0;
}
int main()
{
int a = 0x11223344;
int* pa = &a;
char* pc = (char*)&a;
printf("pa=%p\n", pa);
printf("pa+1=%p\n",pa + 1);
printf("pc=%p\n", pc);
printf("pc+1=%p\n", pc + 1);
return 0;
}
指针的类型决定了指针+1 -1操作的时候,跳过几个字节
(决定了指针的步长)
(2)指针的解引用
int main()
{
int a = 0;
int* pi=&a;//pi 访问4个字节,pi+1也是跳过4个字节
float* pf=&a;//pf解引用访问4个字节,pf+1也是跳过4个字节
//int* 和float*不能通用
//*pi = 100;
//*pf = 100.0;
return 0;
}
3.野指针
(1)野指针就是指针指向的位置是不可知的
int main()
{
int* p;
//p没有初始化,就意味着没有明确的指向
//一个局部变量不初始化的化,放的是随机值
*p = 10;//非法访问内存,这里的p就是野指针
return 0;
}
(2)指针越界访问
int main()
{
int arr[10] = { 0 };
int* p = arr;//&arr[0]
int i = 0;
for (i = 0;i <= 10;i++)
{
*p = i;
p++;//当指针指向的范围超出数组arr的范围时,p就是野指针
}
return 0;
}
(3)指针指向的空间释放
int* test()
{
int a = 10;
return &a;
}
int main()
{
int* p = test();
return 0;
}
//空间已经不属于该程序,但是还存在于内存之中
(4)避免野指针的方法
1.指针初始化
2.小心指针越界
3.指针指向空间释放即时置NULL
4.避免返回局部变量的地址
5.指针使用之前检查有效性
int main()
{
//int b = 0;
//int a = 10;
//int* p = &a;
//*p = 20;
//NULL->0
//int* p2 = NULL;
//*p2 = 100;//err
int* p3 = NULL;
if (p3 != NULL)
{
*p3 = 100;//ok
}
return 0;
}
4.指针运算
指针+-整数
指针-指针
指针的关系运算
4.1指针+-整数
#define N_VALUES 5
float values[N_VALUES];
float* vp;
//指针的关系运算
for (vp = &values[0];vp < &values[N_VALUES];)
{
*vp++ = 0;//*vp->vp++ 注意与(*vp)++的区别
}
4.2指针-指针
int main()
{
int arr[10] = { 0 };
printf("%d\n", &arr[9] - &arr[0]);
return 0;
}
指针-指针得到的绝对值是指针和指针之间的元素个数
不是所有的指针都能相减
指向同一块空间的2个指针才能相减
int main()
{
//int arr[10] = { 0 };
//printf("%d\n", &arr[9] - &arr[0]);
int arr[10] = { 0 };
char ch[5] = { 0 };
printf("%d\n", &ch[0] - &arr[5]);//err
return 0;
}
指针-指针求字符串长度
int my_strlen(char* str)
{
char* start = str;
while(*str !='\0')
{
str++;
}
return (str - start);
}
int main()
{
int len = my_strlen("abcdef");
printf("%d\n", len);
return 0;
}
4.3指针的关系运算
#define N_VALUES 5
float values[N_VALUES];
float* vp;
for (vp = &values[N_VALUES];vp >= &values[0];)
{
*--vp = 0;
}
第二种(不建议)
#define N_VALUES 5
float values[N_VALUES];
float* vp;
for (vp = &values[N_VALUES-1] ;vp >= &values[0];vp--)
{
*vp = 0;
}
5.指针和数组
int main()
{
int arr[10] = { 0 };
//arr是首元素的地址
//&arr[0]
int* p = arr;
//通过指针来访问数组
int sz = sizeof(arr) / sizeof(arr[0]);
int i = 0;
for (i = 0;i < sz;i++)
{
printf("%d ", *(p + i));
}
return 0;
}
int main()
{
int arr[10] = { 0 };
//arr是首元素的地址
//&arr[0]
int* p = arr;
//通过指针来访问数组
int sz = sizeof(arr) / sizeof(arr[0]);
int i = 0;
for (i = 0;i < sz;i++)
{
printf("%p-------%p\n", &arr[i], p + i);
//printf("%d ",arr[i]);
//printf("%d ",*(p+i));
//printf("%d ",*(arr+i));
//arr[i]-->*(arr+i)
}
/*for (i = 0;i < sz;i++)
{
printf("%d ", *(p + i));
}*/
return 0;
}
6.二级指针
#include<stdio.h>
int main()
{
int a = 10;
int* pa = &a;//pa是一级指针变量
int** ppa=&pa;//ppa是一个二级指针变量
**ppa = 20;
//**pa = 20;
printf("%d\n", a);
return 0;
}
二级指针变量是用来存放一级指针变量的地址的
7.指针数组
存放指针的数组
int main()
{
int a = 10;
int b = 20;
int c = 30;
int arr[10];
int* pa = &a;
int* pb = &b;
int* pc = &c;
//parr就是存放指针的数组
//指针数组
int* parr[10] = { &a,&b,&c };
int i = 0;
for (i = 0;i < 3;i++)
{
printf("%d ", *(parr[i]));
}
return 0;
}
int main()
{
int arr1[4] = { 1,2,3,4 };
int arr2[4] = { 2,3,4,5 };
int arr3[4] = { 3,4,5,6 };
int* parr[3] = { arr1,arr2,arr3 };
int i = 0;
for (i = 0;i < 3;i++)
{
int j = 0;
for (j = 0;j < 4;j++)
{
printf("%d ", parr[i][j]);//arr[i]-->*(arr+1)
}
printf("/n");
}
return 0;
}