经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » 程序设计 » C++ » 查看文章
我的改错日常----指针的使用
来源:cnblogs  作者:去留意  时间:2021/5/24 10:58:38  对本文有异议

指针使用守则以及建议

守则1:每一个指针调用前都要有所指向的空间(即地址);

守则2:要修改指针时需要传入更高一级指针;

建议:不要使用指针。

法则及真理详解

守则1:每一个指针调用前都要有所指向的空间(即地址);

当你新建一个指针的时候,都要记住需要为其分配空间,最常见使用malloc函数分配空间。没有分配空间之前不要使用它。指针与地址空间是对应的。没有分配地址的指针指向的空间是不安全的,可能出现问题。只有指针指向的空间是确定的、自己分配的这时候指针才是安全的。

守则2:要修改指针时需要传入更高一级指针;

当使用函数调用修改指针时,一定要记住,参数一定是更高一级的指针,否者不会修改其值。类比变量的修改,假若有一个局部变量int a = 10;调用函数修改a时,函数传入的参数必须时a的地址,才可以修改a的值。否则函数执行完不会修改其值。以此类推,要修改一重指针,函数需要传入二级指针。需要修改二重指针,函数需要传入三重指针。等等。切记,不要看见是指针就直接传入参数调用。一定要分清。

在函数内部赋值时,需要解引用传入的更高一级指针,使其成为要修改的指针类型,再对齐进行修改。当然可以声明变量为p级别指针,而传入&p级指针。

小例子:

  1. // 例1
  2. int a = 0;
  3. void changeA(int *pa)// 传入更高一级指针
  4. {
  5. *pa = 10; // 采用解引用修改值
  6. }
  7. changeA(a);
  8. // 例2
  9. int *b = NULL;
  10. void changeB(int **pb) // 传入更高一级指针
  11. {
  12. *pb = (int*)malloc(sizeof(int)); // 采用解引用修改值
  13. }
  14. changeB(&b);
  15. // 等于例2
  16. int *b = NULL;
  17. b = (int*)malloc(sizeof(int));

建议:不要使用指针。

在你没有完全搞明白指针的时候,建议避免使用指针。可以使用全局变量、通过返回值修改原来的值、C++中函数传入引用等等。如果无法避免,不要使用过高级的指针。

实例

昨天心血来潮敲一下二叉树的建立,没想到直接卡死。

下面是源程序

  1. // 自定义数据类型
  2. typedef char DataType;
  3. // 二叉树的定义
  4. typedef struct Node
  5. {
  6. DataType data; // 数据
  7. struct Node* LChild; // 左子树
  8. struct Node* RChild; // 右子树
  9. }BiTNode,*BiTree; //BiTNode:二叉树类型 BiTree:指针类型
  10. /*
  11. * 建立二叉树
  12. * 采用类似先序遍历的方式建立二叉树。
  13. * 首先读入的是当前根节点的数据,如果是“.”,则将当前树的根置为空,否则申请一个新节点,
  14. * 存入当前的数据,分别用用当前节点的左子域和右子域进行递归调用创建左子树右子树。
  15. */
  16. void CreateBiTree(BiTree* bt)
  17. {
  18. char ch;
  19. ch = getchar();
  20. if (ch == '.') *bt = NULL;
  21. else {
  22. (*bt) = (BiTree)malloc(sizeof(BiTNode));
  23. if ((*bt) != NULL) { // C6011警告 C++ malloc申请的节点使用前先判空
  24. (*bt)->data = ch;
  25. CreateBiTree(&((*bt)->LChild));
  26. CreateBiTree(&((*bt)->RChild));
  27. }
  28. }
  29. }

然而我是这样调用的:

  1. // 初始化二叉树
  2. void InitBiTree(BiTree* bt)
  3. {
  4. bt = (BiTree*)malloc(sizeof(BiTree));
  5. }
  6. int main()
  7. {
  8. BiTree* tree = NULL;
  9. InitBiTree(tree);
  10. CreateBiTree(tree);
  11. }

出现如下报错

出错原因:

当然CreateBiTree(BiTree* bt)函数是没有任何问题的,问题就出在InitBiTree(tree)上,但是确实使用InitBiTree给tree初始化分配空间了,而且传入的是指针。但是为什么tree是nullptr呢?这时候请看回头看守则1与守则2。为什么会报错?因为tree没有指向的空间,守则1不满足。为什么tree没有指向分配的空间?因为tree的值没有修改,而修改指针的值,请参照守则2,必须传入更高一级的指针。InitBiTree(tree)不满足守则2。

正确调用如下:

  1. #include<iostream>
  2. #include <stdio.h>
  3. #include <stdlib.h>
  4. // 自定义数据类型
  5. typedef char DataType;
  6. // 二叉树的定义
  7. typedef struct Node
  8. {
  9. DataType data; // 数据
  10. struct Node* LChild; // 左子树
  11. struct Node* RChild; // 右子树
  12. }BiTNode,*BiTree; //BiTNode:二叉树类型 BiTree:指针类型
  13. /*
  14. * 建立二叉树
  15. * 采用类似先序遍历的方式建立二叉树。
  16. * 首先读入的是当前根节点的数据,如果是“.”,则将当前树的根置为空,否则申请一个新节点,
  17. * 存入当前的数据,分别用用当前节点的左子域和右子域进行递归调用创建左子树右子树。
  18. */
  19. void CreateBiTree(BiTree* bt)
  20. {
  21. char ch;
  22. ch = getchar();
  23. if (ch == '.') *bt = NULL;
  24. else {
  25. (*bt) = (BiTree)malloc(sizeof(BiTNode));
  26. if ((*bt) != NULL) { // C6011警告 C++ malloc申请的节点使用前先判空
  27. (*bt)->data = ch;
  28. CreateBiTree(&((*bt)->LChild));
  29. CreateBiTree(&((*bt)->RChild));
  30. }
  31. }
  32. }
  33. void InitBiTree(BiTree **bt)
  34. {
  35. // 分配空间
  36. *bt = (BiTree*)malloc(sizeof(BiTree));
  37. }
  38. int main()
  39. {
  40. BiTree* tree = NULL;
  41. InitBiTree(&tree);
  42. CreateBiTree(tree);
  43. return 0;
  44. }

解释:

声明BiTree* tree = NULL;后需要对其进行修改,即分配内存,如使用函数调用的方式参考守则2,必须传入更高一级指针。而且赋值时采用解引用的方式,即*变量名的方式。

或者如下:

  1. #include<iostream>
  2. #include <stdio.h>
  3. #include <stdlib.h>
  4. // 自定义数据类型
  5. typedef char DataType;
  6. // 二叉树的定义
  7. typedef struct Node
  8. {
  9. DataType data; // 数据
  10. struct Node* LChild; // 左子树
  11. struct Node* RChild; // 右子树
  12. }BiTNode,*BiTree; //BiTNode:二叉树类型 BiTree:指针类型
  13. /*
  14. * 建立二叉树
  15. * 采用类似先序遍历的方式建立二叉树。
  16. * 首先读入的是当前根节点的数据,如果是“.”,则将当前树的根置为空,否则申请一个新节点,
  17. * 存入当前的数据,分别用用当前节点的左子域和右子域进行递归调用创建左子树右子树。
  18. */
  19. void CreateBiTree(BiTree* bt)
  20. {
  21. char ch;
  22. ch = getchar();
  23. if (ch == '.') *bt = NULL;
  24. else {
  25. (*bt) = (BiTree)malloc(sizeof(BiTNode));
  26. if ((*bt) != NULL) { // C6011警告 C++ malloc申请的节点使用前先判空
  27. (*bt)->data = ch;
  28. CreateBiTree(&((*bt)->LChild));
  29. CreateBiTree(&((*bt)->RChild));
  30. }
  31. }
  32. }
  33. int main()
  34. {
  35. BiTree tree = NULL;
  36. CreateBiTree(&tree);
  37. return 0;
  38. }

解释:

声明BiTree tree = NULL;这时候tree本身有地址,但是没有指向的地址。CreateBiTree(&tree);传入tree的地址,使用解引用“ *bt = NULL; ” ,“ (*bt) = (BiTree)malloc(sizeof(BiTNode)); ”等来修改tree符合守则2。所以正确。

两个程序最重要的区别就是tree的类型不同。

当然也可以使用如下程序调用

  1. #include<iostream>
  2. #include <stdio.h>
  3. #include <stdlib.h>
  4. // 自定义数据类型
  5. typedef char DataType;
  6. // 二叉树的定义
  7. typedef struct Node
  8. {
  9. DataType data; // 数据
  10. struct Node* LChild; // 左子树
  11. struct Node* RChild; // 右子树
  12. }BiTNode,*BiTree; //BiTNode:二叉树类型 BiTree:指针类型
  13. /*
  14. * 建立二叉树
  15. * 采用类似先序遍历的方式建立二叉树。
  16. * 首先读入的是当前根节点的数据,如果是“.”,则将当前树的根置为空,否则申请一个新节点,
  17. * 存入当前的数据,分别用用当前节点的左子域和右子域进行递归调用创建左子树右子树。
  18. */
  19. void CreateBiTree(BiTree* bt)
  20. {
  21. char ch;
  22. ch = getchar();
  23. if (ch == '.') *bt = NULL;
  24. else {
  25. (*bt) = (BiTree)malloc(sizeof(BiTNode));
  26. if ((*bt) != NULL) { // C6011警告 C++ malloc申请的节点使用前先判空
  27. (*bt)->data = ch;
  28. CreateBiTree(&((*bt)->LChild));
  29. CreateBiTree(&((*bt)->RChild));
  30. }
  31. }
  32. }
  33. int main()
  34. {
  35. BiTree *tree = NULL;
  36. tree = (BiTree*)malloc(sizeof(BiTree)); // 直接分配,不使用初始化函数。
  37. CreateBiTree(tree);
  38. return 0;
  39. }

总结

C/C++语言十分灵活,使用指针的时候可以采取多种调用以及声明的方式,根据自己日常习惯选择就行。但是在使用的时候一定要分清指针是否有所指向的地址空间以及调用函数的时候传入参数的类型。

每一个指针都要有所指向的空间(即地址);

要修改指针时需要传入更高一级指针;

如果对指针的使用还是不够熟练建议避免使用指针。

原文链接:http://www.cnblogs.com/daidh/p/14782781.html

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号