百度地图api wordpress,长春百度seo代理,上海做网站 公司,网站开发的工作方法目录
1. 指针的运算
2. 野指针和悬空指针
2.1 野指针
2.2 悬空指针
3. void类型指针
4. 二级指针和多级指针
4.1 命名规则
4.2 作用
4.2.1 二级指针可以操作一级指针记录的地址
4.2.2 利用二级指针获取变量中记录的数据 1. 指针的运算 文章开始前可以先了…
目录
1. 指针的运算
2. 野指针和悬空指针
2.1 野指针
2.2 悬空指针
3. void类型指针
4. 二级指针和多级指针
4.1 命名规则
4.2 作用
4.2.1 二级指针可以操作一级指针记录的地址
4.2.2 利用二级指针获取变量中记录的数据 1. 指针的运算 文章开始前可以先了解C语言指针·入门用法超详解-CSDN博客 通过上一章我们初步了解了指针的用法知道指针的类型是 其中指针中数据类型的作用是获取字节数据的个数正常情况下变量p只能获取到0x001的内存地址而int型数据占4字节因此 那么我们可以思考一下若是
int a10;
int* pa;p1 假设a的地址为0x01那么p1指向的地址会是什么呢 会是0x02还是0x05呢 正确答案应该是0x05这是为什么呢 步长指针移动一次的字节个数 因为指针的加法操作实际上是将指针向后移动若干个存储单元而不是简单的数学加法上面我们也提到了正常情况下变量p只能获取到0x01的内存地址而int型数据占4字节而p1就是指针移动一步一步在这里是四个字节因此p1最终会移动到0x05的位置。我们拿代码验证一下
#include stdio.hint main()
{/** 指针的运算* 步长指针移动一次走了多少字节* char1* short2* int4* long4* long long8*///加法指针往后移动了N步PN//减法指针往前移动了N步P-Nint a 10;int* p a;printf(%p\n, p);printf(%p\n, p 1);printf(%p\n, p 2);printf(%p\n, p - 1);printf(%p\n, p - 2);return 0;
}注意 指针有意义的操作 指针跟整数进行加、减操作(每次移动N个步长) 指针跟指针进行减操作(间隔步长) #include stdio.hint main()
{/** 有意义的操作指针跟整数进行加、减操作(每次移动N个步长)指针跟指针进行减操作(间隔步长)无意义的操作指针跟整数进行乘除操作原因此时指针指向不明指针跟指针进行加、乘、除操作*///前提条件保证内存空间是连续的//数组int arr[] { 1,2,3,4,5,6,7,8,9 };//获取0索引的内存地址int* p1 arr[0];//指针跟整数进行加、减操作(每次移动N个步长)//通过内存地址获取数据printf(%d\n, *p1);printf(%d\n, *(p1 1));//获取5索引的内存地址int* p2 arr[5];//p2 - p1间隔了多少步长printf(%d\n, p2 - p1);printf(%p\n, p1);printf(%p\n, p2);return 0;
}指针无意义的操作 指针跟整数进行乘除操作 原因此时指针指向不明 指针跟指针进行加、乘、除操作 2. 野指针和悬空指针
2.1 野指针 野指针指针指向的空间未分配。
#include stdio.hint main()
{/*野指针指针指向的空间未分配悬空指针指针指向的空间已分配但是被释放了*///野指针指针指向的空间未分配int a 10;int* p1 a;printf(%p\n, p1);printf(%d\n, *p1);//p2为野指针int* p2 p1 10;printf(%p\n, p2);printf(%d\n, *p2);return 0;
}此时运行程序虽然也能得到p2的地址但是要知道这块地址我们并没有给他分配他虽然能找到地址但是若是随意修改数据在正常使用中可能会修改别的函数的数据导致最终运行错误 2.2 悬空指针 悬空指针指针指向的空间已分配但是被释放了。
#include stdio.hint* method();int main()
{/*野指针指针指向的空间未分配悬空指针指针指向的空间已分配但是被释放了*///悬空指针指针指向的空间已分配但是被释放了int* p3 method();printf(拖点时间\n);printf(拖点时间\n);printf(拖点时间\n);printf(拖点时间\n);printf(拖点时间\n);printf(拖点时间\n);printf(%p\n, p3);printf(%d\n, *p3);return 0;
}int* method()
{int num 10;int* p num;return p;
} 会发现此时代码数据错误正常p3应当显示10 这里可以调用static来使用
#include stdio.hint* method();int main()
{/*野指针指针指向的空间未分配悬空指针指针指向的空间已分配但是被释放了*///悬空指针指针指向的空间已分配但是被释放了int* p3 method();printf(拖点时间\n);printf(拖点时间\n);printf(拖点时间\n);printf(拖点时间\n);printf(拖点时间\n);printf(拖点时间\n);printf(%p\n, p3);printf(%d\n, *p3);return 0;
}int* method()
{static int num 10;int* p num;return p;
} 3. void类型指针 特殊类型void* p 不表示任何类型只能记录地址值不能获取到变量里面的数据也不能进行加减的计算。 特点无法获取数据无法计算但是可以接收任意地址数据。 在我们使用指针的过程中会发现不同类型的指针之间是不能相互赋值的否则会发生编辑错误
#include stdio.hint main()
{//void类型指针//定义两个变量int a 10;short b 20;//定义两个指针int* p1 a;short* p2 b;//输出打印printf(%d\n, *p1);printf(%d\n, *p2);//不同类型的指针之间是不能相互赋值的char* p3 p1;printf(%d\n, *p3);//这里编译器为我们进行了强制类型转换上面的过程相当于如下char* p4 (char*)p1;printf(%d\n, *p4);return 0;
} 这里的指针间进行复制那是因为编译器在编译过程中对p1进行了强制类型转换p3的实际流程如p4所示 为了解决这一问题我们可以将数据类型定义为void不过这也会导致不能printf输出数据因为void不能获取到变量里面的数据也不能进行加减的计算否则编译器会报错
#include stdio.hint main()
{//void类型指针//定义两个变量int a 10;short b 20;//定义两个指针int* p1 a;short* p2 b;//输出打印printf(%d\n, *p1);printf(%d\n, *p2);//不同类型的指针之间是不能相互赋值的char* p3 p1;printf(%d\n, *p3);//这里编译器为我们进行了强制类型转换上面的过程相当于如下char* p4 (char*)p1;printf(%d\n, *p4);//void类型指针打破上面的观念//void没有任何类型好处可以接收任意类型指针记录内存地址void* p5 p1;void* p6 p2;//缺点不能获取到变量里面的数据也不能进行加减的计算//printf(%d\n, *p5);//printf(%d\n, *p6);//printf(%d\n, *p5 - 1);//printf(%d\n, *p6 1);return 0;
} 那么我们引用void有什么用呢 例如我们用于调用函数进行交换数据我们可以编写如下代码
#include stdio.hvoid swap(void* p1, void* p2);int main()
{//void类型指针//定义两个变量int a 10;short b 20;//定义两个指针int* p1 a;short* p2 b;//输出打印printf(%d\n, *p1);printf(%d\n, *p2);//不同类型的指针之间是不能相互赋值的char* p3 p1;printf(%d\n, *p3);//这里编译器为我们进行了强制类型转换上面的过程相当于如下char* p4 (char*)p1;printf(%d\n, *p4);//void类型指针打破上面的观念//void没有任何类型好处可以接收任意类型指针记录内存地址void* p5 p1;void* p6 p2;//缺点不能获取到变量里面的数据也不能进行加减的计算//printf(%d\n, *p5);//printf(%d\n, *p6);//printf(%d\n, *p5 - 1);//printf(%d\n, *p6 1);//调用函数交换数据int c 100;int d 200;swap(c, d);printf(c%d,d%d\n, c, d);return 0;
}//函数用来交换两个变量记录数据void swap(int* p1, int* p2)
{int temp *p1;*p1 *p2;*p2 temp;
} 此时可以实现数据的交换 但是若是此时我想使用long long型数据呢数据会发生报错我在DevC上运行报错在VS上运行正确因为VS在这里编辑器给他自动强制类型转换了
#include stdio.hvoid swap(void* p1, void* p2);int main()
{//void类型指针//定义两个变量int a 10;short b 20;//定义两个指针int* p1 a;short* p2 b;//输出打印printf(%d\n, *p1);printf(%d\n, *p2);//不同类型的指针之间是不能相互赋值的char* p3 p1;printf(%d\n, *p3);//这里编译器为我们进行了强制类型转换上面的过程相当于如下char* p4 (char*)p1;printf(%d\n, *p4);//void类型指针打破上面的观念//void没有任何类型好处可以接收任意类型指针记录内存地址void* p5 p1;void* p6 p2;//缺点不能获取到变量里面的数据也不能进行加减的计算//printf(%d\n, *p5);//printf(%d\n, *p6);//printf(%d\n, *p5 - 1);//printf(%d\n, *p6 1);//调用函数交换数据long long c 100L;long long d 200L;swap(c, d);printf(c%lld,d%lld\n, c, d);return 0;
}//函数用来交换两个变量记录数据void swap(int* p1, int* p2)
{int temp *p1;*p1 *p2;*p2 temp;
}那么我们如何才能进行不同类型都能调用该函数呢可以使用void类型
void swap(void* p1, void* p2)
{int temp *p1;*p1 *p2;*p2 temp;
} 但是如果使用void又会出现新的问题就是void不能获取到变量里面的数据也不能进行加减的计算那么要如何解决呢 这里将void*类型的指针p1和p2分别转换为char*类型的指针pc1和pc2。这是因为char类型是 C 语言中的基本数据类型且大小为1字节所以可以通过char*指针逐字节访问内存。 同时函数void swap(void* p1, void* p2, int len)加上一个len用于表示字节数要是int型len就等于4long long就是等于8在x64环境下
void swap(void* p1, void* p2, int len)
{//把void类型的指针转换char类型的指针char* pc1 p1;char* pc2 p2;char temp 0;//以字节为单位一个字节一个字节的进行转换for (int i 0; i len; i){temp *pc1;*pc1 *pc2;*pc2 temp;pc1;pc2;}
} 完整程序代码
#include stdio.hvoid swap(void* p1, void* p2, int len);int main()
{//void类型指针//定义两个变量int a 10;short b 20;//定义两个指针int* p1 a;short* p2 b;//输出打印printf(%d\n, *p1);printf(%d\n, *p2);//不同类型的指针之间是不能相互赋值的char* p3 p1;printf(%d\n, *p3);//这里编译器为我们进行了强制类型转换上面的过程相当于如下char* p4 (char*)p1;printf(%d\n, *p4);//void类型指针打破上面的观念//void没有任何类型好处可以接收任意类型指针记录内存地址void* p5 p1;void* p6 p2;//缺点不能获取到变量里面的数据也不能进行加减的计算//printf(%d\n, *p5);//printf(%d\n, *p6);//printf(%d\n, *p5 - 1);//printf(%d\n, *p6 1);//调用函数交换数据int c 100;int d 200;swap(c, d, 4);printf(c%d,d%d\n, c, d);return 0;
}//函数用来交换两个变量记录数据
/*
void swap(int* p1, int* p2)
{int temp *p1;*p1 *p2;*p2 temp;
}
*///修改一下函数更具有通用性
//因为以上函数若是主函数调用的话只能int类型的数据
void swap(void* p1, void* p2, int len)
{//把void类型的指针转换char类型的指针char* pc1 p1;char* pc2 p2;char temp 0;//以字节为单位一个字节一个字节的进行转换for (int i 0; i len; i){temp *pc1;*pc1 *pc2;*pc2 temp;pc1;pc2;}
}4. 二级指针和多级指针
4.1 命名规则 以二级指针为例上一章最初我们了解了什么是指针 C语言指针·入门用法超详解-CSDN博客 那么既然普通变量就有指针指针也是一个变量为什么不能有一个指针继续指向他呢那么我们可以了解到 既然指针也有他的指针那么指针的指针要怎么命名呢 其和指针的命名规则是一样的也是 数据类型 * 变量名 但是需要注意的是指针的数据类型要跟指向空间中的数据的类型保持一致。 首先对于指针p其指向数据a的地址需要和a数据类型保持一致那么指针的命名就是 int * p 数据类型 标记 变量名 然后二级指针指向的是指针的数据类型此时指针空间内存储的不是数据而是a的地址他的数据类型是int*也就是说二级指针的命名 int* * p 数据类型 标记 变量名 4.2 作用
4.2.1 二级指针可以操作一级指针记录的地址 上代码
#include stdio.hint main()
{//定义变量int a 10;int b 20;//定义一级指针int* p a;printf(a的地址%p\n, a);printf(b的地址%p\n, b);printf(修改前p的地址%p\n, p);//定义二级指针int** pp p;*pp b;printf(修改后p的地址%p\n, p);return 0;
}可以发现p的地址被修改了简单点来说初始时p指向变量a的地址。然后通过pp这个二级指针修改了p的指向使其指向了变量b的地址。因此最后输出显示p的地址发生了变化从指向a的地址变为指向b的地址。
4.2.2 利用二级指针获取变量中记录的数据
#include stdio.hint main()
{//定义变量int a 10;int b 20;//定义一级指针int* p a;//定义二级指针int** pp p;printf(修改前获取变量里面的数据%d\n, **pp);*pp b;printf(修改后获取变量里面的数据%d\n, **pp);return 0;
}C语言指针·入门用法超详解-CSDN博客 指针_时光の尘的博客-CSDN博客