Chinaunix首页 | 论坛 | 博客
  • 博客访问: 201673
  • 博文数量: 24
  • 博客积分: 608
  • 博客等级: 中士
  • 技术积分: 371
  • 用 户 组: 普通用户
  • 注册时间: 2012-04-22 21:10
文章分类

全部博文(24)

文章存档

2012年(24)

分类: C/C++

2012-09-03 16:04:16

比如如下代码

点击(此处)折叠或打开

  1. void create3(List* head, int *a, int n)
  2. {
  3.     printf("head2 = 0x%x\n", head);
  4.     head = (List*)malloc(sizeof(List));
  5.     head->val = 1;
  6.     head->next = NULL;
  7.     printf("head4 = 0x%x\n", head);
  8. }
  9. int main()
  10. {
  11.     int a[] = {3, 1, 5, 4, 7, 9, 2};
  12.     int i, len = sizeof a / sizeof a[0];
  13.     List* head;
  14.     printf("head1 = 0x%x\n", head);
  15.     create3(head, a, len);
  16.     printf("head3 = 0x%x\n", head);
  17. }
经常会在写链表的时候犯这个错误,曾经也百思不得其解,为什么最后会错呢?其实不难理解,我们看最后的输出吧:
head1 = 0x28ff94
head2 = 0x28ff94
head4 = 0x910e98
head3 = 0x28ff94

发现head4与其他几值不一样了,但是当函数结束了,head3还是之前的值,也就是说这个head进函数之后返回依然没有改变其值。不妨分析一下,首先,在main函数里面定义了结构体指针head,也没有初始化他,此时head指向的什么乱七八糟的也不知道,当以传值的方式进入函数以后,事实上create3把参数List* head拷贝了一份,然后修改了head的值,但是主函数里面的head是无辜的,他没有修改。是不是很眼熟,那个熟悉的swap的例子就是类似的原理,除非用C++的引用。
一个可行的方法,在不改变主函数的方式下:

点击(此处)折叠或打开

  1. void create2(List** head, int *a, int n)
  2. {
  3.     *head = (List*)malloc(sizeof(List));
  4.     (*head)->next = NULL;
  5.     create(*head, a, n);
  6. }
  7. int main()
  8. {
  9. /// .......
  10. create2(&head, a, len);
  11. /// .......
  12. }
以传递指针的指针传递进去,也就是传递head的地址,这个时候其实把head的地址传递进去了,那head的地址是没有修改过的,但是head的值仍然是个结构体的地址,修改了head的值之后,主函数的也随着修改了。一句话,函数改变了head里面的值,但是传递的地址没有修改,虽然是拷贝过去的。画个图

分别表示传递前和传递后的状态。分别表示&head和head,我们发现head的值是变过了,但是head的地址依旧是那个!

阅读(2624) | 评论(1) | 转发(3) |
给主人留下些什么吧!~~

ChianXu2012-09-05 08:41:06

新手很容易犯这个错。我反正之前一直犯错。后面渐渐的明白了。