文章目录
一、指针是什么
电线控制电信号—转换数字信号产生二进制序列
二、指针和指针类型
指针类型的意义
1、
指针类型决定了指针进行解引用操作时,能访问空间的大小
int* p;*p 能够访问4字节
char p;*p能够访问1字节(只认为p是字符)
double p ;*p能访问8字节
int main()
{
printf("%d\n",sizeof(char*)); //都是存放地址,32位下,都是4字节
printf("%d\n",sizeof(short*));
printf("%d\n",sizeof(int*));
printf("%d\n",sizeof(double*));
printf("%d\n",sizeof(float*));
return 0;
}
2、
指针类型决定了,指针走一步走多远(指针步长),单位字节。
int* p;p+1(访问下一个整型)–>4个字节(间隔)
char* p;p+1–>1个字节
double* p;p+1–>8个字节
三、野指针
1、概念:
指针指向的位置是不可知的(随机的、不正确的、没有明确限制的)
2、成因:
(1)指针未初始化,(局部变量不初始化,默认随机值)
局部指针变量,被初始化为随机值
(犹如流浪者,想睡哪睡哪)
int main()
{
int a;//局部变量不初始化也默认为是随机值
int* p;//局部指针未初始化,默认是随机值
*p =20;
return 0;
}
(2)指针越界访问
(喝了假酒,住了别人家的房子)
int main()
{
int arr[10]={0};
int* p=arr;
int i=0;
for(i=0;i<10;i++)
{
*(p++)=i; //指针范围超出数组范围时,p就是野指针
}
return 0;
}
int main()
{
int a[10]={0};
int* p=a;
for(i=0;i<=12;i++)
{
*p=i;
p++; //p为指针
//上述两行代码等价于*p++;
}
return 0;
}
(3)指针指向的空间释放
(就像 之前是自己的房子,要住的时候突然成别人的了)
int* text()
{
int a=10; //局部变量,出作用域自动销毁
return &a;
}
int main()
{
int* p=test(); //a仅仅为局部变量,超出范围自动销毁,所以找不到该空间
*p =20;
return 0;
}
3、如何避免野指针
(1)指针初始化
把某值的地址给它
不知道给什么指针时,赋予空指针(NULL)
int main()
{
int a=1;
int b=10;
int* pa=&a; //初始化
int* p=NULL; //不知道赋值什么的时候一种方法,空指针
return 0;
}
(2)小心指针越界
(3)指针指向空间释放,可使其置为NULL
(4)指针使用前检查有效性
四、指针运算
1、指针±整数
用来改变要访问的地址
举例:用指针来访问数组
int main()
{
int arr[10]={1,2,3,4,5,6,7,8,9,10};
int i=0;
//int sz=sizeof(arr)/sizeof(arr[0]); 不清楚元素个数时,可以使用
int* p=arr;
for(i=0;i<10;i++)
{
printf("%d\n",*p);
p++;
}
return 0;
}
int main()
{
int arr[10]={1,2,3,4,5,6,7,8,9,10};
int i=0;
//int sz=sizeof(arr)/sizeof(arr[0]); 不清楚元素个数时,可以使用
int* p=arr;
for(i=0;i<5;i++)
{
printf("%d\n",*p);
p+=2; //只访问1,3,5,7,9(每次间隔2个)
}
return 0;
}
int main()
{
int arr[10]={1,2,3,4,5,6,7,8,9,10};
int i=0;
//int sz=sizeof(arr)/sizeof(arr[0]); 不清楚元素个数时,可以使用
int* p=&arr[9]; //将最后一个元素放入p中
for(i=0;i<5;i++)
{
printf("%d\n",*p);
p-=2; //倒序访问(因为将数组的最后一个元素放入,且-=2,每次左移)10,8,6,4,2(每次间隔2个)
}
return 0;
}
2、指针-指针
得到的是两指针中间的元素个数(大地址-小地址)
中间元素个数有问题,可以理解为两地址间的距离
(小地址-大地址)的绝对值是两地址间的距离
不同类型的指针不可相减(例如,char指针和int指针不可相减),否则得到的是不可预知的值
int main()
{
int arr[10]={1,2,3,4,5,6,7,8,9,10};
printf("%d\n",&arr[9]-&arr[0]);
return 0;
}
实用方法:求字符串的长度
int my_strlen(char* str)
{
char* start =str;
char* end =str;
while(*end!='\0')
{
end++;
}
return end-start;
}
int main()
{
char arr[]="bit";
int len=my_strlen(arr);
printf("%d\n",len);
return 0;
}
3、指针的关系运算
指针比较大小(指针的关系运算)
五、指针和数组
数组可以通过指针来访问
//关于数组名
int main()
{
int arr[10]={0};
printf("%p\n",arr); //地址-首元素地址
printf("%p\n",&arr[0]);
retuurn 0;
}
int main()
{
int arr[9]={0};
int* p=arr;
int i=0;
for(i=0;i<10;i++)
{
*(p+i)=i; //放入整型元素
}
for(i=0;i<10;i++)
{
//printf("%d\n",arr[i]); //输出整型元素
printf("%d\n",*(p+i));//输出整型元素 ,两者输出相同
}
return 0;
}
六、二级指针
int main()
{
int a=1;
int* pa=&a;
int** ppa=&pa;//ppa为二级指针
int*** pppa=&ppa;//pppa为三级指针
**ppa=20; //**ppa即为a的值
printf("%d\n",**ppa);
printf("%d\n",a); //和上方输出内容相同
return 0;
}
七、指针数组(本质是数组)
指针数组(用来存放指针的数组)
int main()
{
int a=10;
int b=20;
int c=30;
int i=0;
int* arr2[3]={&a,&b,&c}; //指针数组
for(i=0;i<3;i++)
{
printf("%d\n",*(arr2[i])); //通过对地址解引用操作可得a,b,c的值,arr2[i]就是地址
}
return 0;
}
整型数组(用来存放整型)
字符数组(用来存放字符)
数组指针(本质是指针)