#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
//----------------------------------------------------------------------------------------------------------3. 野指针
// 野指针就是指针指向的位置是不可知的(随机的、不正确的、没有明确限制的)
//---------------------------------------------------------------------------------------------3.1 野指针成因
//-------------------------------------------------1.没有初始化
int main()
{
int* p;
//p没有初始化,没有明确指向
//一个局部变量如果不初始化的话,放的是随机值0xcccccccc
*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++) //当指针指向的范围超出数组arr的范围时,p就是野指针
{
*p = i;
p++;
}
return 0;
}
//-------------------------------------------------3. 指针指向的空间释放
int* test()
{
int a = 10;
return &a;
}
int main()
{
int* p = test();
//p是野指针,局部变量 a 在函数调用结束后就销毁了,但是 a 的地址被保存到了 p 里,
//根据p 里保存的地址,不能再访问到局部变量 a, 所以 p 就成了野指针
return 0;
}
//---------------------------------------------------------------------------------------------3.2 如何规避野指针
(1). 指针初始化
(2). 小心指针越界
(3). 指针指向空间释放即使置NULL
(4). 避免返回局部变量的地址
(5). 指针使用之前检查有效性
int main()
{
int a = 0;
int* p = &a;
*p = 20;
int* p1 = NULL; //初始化空指针 0
*p1 = 100; // 错误 ×××××××××× 空指针不能直接访问
//空指针怎么用?
int* p2 = NULL;
if (p2 != NULL)
{
*p2 = 100;
}
return 0;
}
int* test()
{
int a = 10;
return &a;
}
int main()
{
int* p = test();
if (p != NULL)
{
printf("%d\n",*p); // 10
//函数调用结束后存储局部变量 a 的那块空间被释放了,
//但是内存中这块空间依旧在操作系统中,如果没有被覆盖,里边的内容依旧存在
}
return 0;
}
//-----------------------------------------------------------------------------------------------------------4. 指针运算
1 指针+-整数
2 指针-指针
3 指针的关系运算//----------------------------------------------------------------------------------------4.1 指针+-整数
//---------------------------------------------------------例一
#define N_VALUES 5
int main()
{
float values[N_VALUES];
float* vp;
//指针+-整数;指针的关系运算
for (vp = &values[0]; vp < &values[N_VALUES];)
{
*vp++ = 0; // 先*vp=0, 后vp++
//*vp++; 先 *vp,然后地址vp++;
// (*vp)++; 对vp指向的对象进行++,也就是地址里的内容++。
}
return 0;
}
//---------------------------------------------------------例二
//让数组内每个元素都为1
int main()
{
int arr[10] = { 0 };
int sz = sizeof(arr) / sizeof(arr[0]);
int i = 0;
//--------------------方法1:通过数组下标
for (i = 0; i < sz; i++)
{
arr[i] = 1;
}
//--------------------方法2:通过指针
int* p = arr;
for (i = 0; i < sz; i++)
{
*p = 1;
p++;
}
//--------------------方法3:通过指针优化版
int* p = arr;
for (i = 0; i < sz; i++)
{
*(p+i) = 1;
}
return 0;
}
//-------------------------------------------------------------------------------------4.2 指针-指针
|指针-指针| 得到的是两个指针之间元素的个数
不是所有的指针都能相减,指向同一块空间的指针相减才有意义
int main()
{
// 指向同一块空间的指针相减才有意义
int arr[10] = { 0 };
printf("%d\n", &arr[9] - &arr[0]);// 9
printf("%d\n", &arr[0] - &arr[9]);// -9
//两者不在同一块空间内,相减没意义
int arr1[5] = { 0 };
char arr2[10] = { 0 };
printf("%d\n", &arr1[4] - &arr1[0]);
return 0;
}
//指针相减的用法
//--------------------------------------版本1:地址++
int my_strlen(char* str)
{
int count = 0;
while (*str != '\0')
{
count++;
str++;
}
return count;
}
//--------------------------------------版本2:递归
int my_strlen(char* str)
{
}
//--------------------------------------版本3:指针-指针
int my_strlen(char* str)
{
char* start = str;
while (*str != '\0')
{
str++;
}
return (str - start);
}
// 自己实现 strlen 函数的作用
int main()
{
//char arr[10] = "abcdef";
int len = my_strlen("abcdef"); //传过去的是字符串的首地址
printf("%d\n", len); //6
return 0;
}
//-----------------------------------------------------------------------------------------4.3 指针的关系运算
(比较大小)
#define N_VALUES 5
int main()
{
float values[N_VALUES]; // 有五个元素的数组
float* vp;
for (vp = &values[N_VALUES]; vp > &values[0];) //指针相比较
{
*--vp = 0; // vp--, *vp=0
}
//简化版,不推荐(可能不符合标准)
for (vp = &values[N_VALUES-1]; vp > &values[0] ; vp--)
{
*vp = 0;
}
//标准规定
//允许指向数组元素的指针与指向数组最后一个元素后面的那个内存位置的指针比较,
// 但是不允许与指向第一个元素之前的那个内存位置的指针进行比较。
return 0;
}
标签:arr,return,int,鹏哥,C语言,vp,++,指针
From: https://blog.csdn.net/most_wanted_/article/details/142988628