双指针指针

时间:2018-09-09 13:07:15

标签: c pointers linked-list double-pointer

为什么不能将指针分配给双指针的指针?我每次都会遇到细分错误。

#include <stdio.h>

int main() {
    int **pointer1, *pointer2, *pointer3, var;

    var = 10;
    pointer3 = &var; 
    pointer1 = &pointer3;
    pointer2 = *pointer1;   //correcting my mistake, so this is now correct?

    return 0;
}

我实际上正在处理的代码,正在练习链表:

#include <stdio.h>
#include <stdlib.h>

typedef struct node_t {
    int num;
    struct node_t *next;
} node_t;

void insert(int, node_t**);

int main(void) {
    int list;
    node_t **head, *temp;

    *head = NULL;

    while (scanf("%d", &list) != EOF) {
        insert(list, head);
    }
    temp = *head;
    /*while (temp != NULL) {      //here is the problem, if I remove this 
                                  //I get segmentation fault but it runs 
        printf("%d ", temp->num); //runs fine when I include it
        temp = temp->next;

    }*/
    return 0;
}

void insert(int list, node_t **head) {
    node_t *temp = malloc(sizeof(node_t));
    temp->next = (*head);
    temp->num = list;
    (*head) = temp;
}

就像我在代码注释中输入的内容一样,当我在不使用while循环的情况下对其进行编译时,上述代码的版本会出现分段错误。但是很奇怪的是,一旦包含while循环,它就可以正常工作。摆弄之后,我怀疑罪魁祸首是我试图将辅助地址分配给常规指针的双指针。 但是此版本实际上运行良好:

#include <stdio.h>
#include <stdlib.h>

typedef struct node_t {
    int num;
    struct node_t *next;
} node_t;

void insert(int, node_t**);

int main(void) {
    int list;
    node_t *head, *temp;

    head = NULL;

    while (scanf("%d", &list) != EOF) {
        insert(list, &head);
    }
    temp = head;
    while (temp != NULL) {

        printf("%d ", temp->num);
        temp = temp->next;

    }
    return 0;
}

void insert(int list, node_t **head) {
    node_t *temp = malloc(sizeof(node_t));
    temp->next = (*head);
    temp->num = list;
    (*head) = temp;
}

在这里,我将地址传递给了链表函数,基本上我在做同样的事情,但是没有双指针。

另一方面,我看到了链表的许多不同实现。我的需要双指针,因为我使用的是void insert(int, **node_t),但是有些版本可以返回地址并更新标头:node_t* insert(int, *node_t)和全局链接列表:void insert(int)。只是想知道实际上推荐哪个版本,更容易调试并且对新手友好。

2 个答案:

答案 0 :(得分:2)

您的第一个示例段错误是因为 <body> <%String name = request.getParameter("inputString");%> <h1>Creating Client Applications</h1> <p>Client Sent... <%=name%> ...to Server</p> <% //String serverInput = "bottle"; try{ int character; Socket socket = new Socket("127.0.0.1", 1234); OutputStream outSocket = socket.getOutputStream(); String str = name; byte buffer[] = str.getBytes(); outSocket.write(buffer); socket.close(); } catch(java.net.ConnectException e){ %> You must first start the server application at the command prompt. <% } %> </body> (及其前面的*pointer1)没有指向任何东西。这是一个未初始化的指针,指向内存中的随机垃圾数据。

尝试取消引用这样的指针(pointer1)将导致**pointer1 = 10;

第一个示例可用的解决方案是为您要存储的数据分配一些内存:

segfault

答案 1 :(得分:1)

执行此操作时:

 **pointer1 = 10;

这表示“获取存储在pointer1中的地址,取消引用该地址,获取存储的地址那里,再次取消引用,然后将值10存储在该位置”。 / p>

它看起来像这样:

pointer1
-------     -------    ------
|  .--|---->|  .--|--->| 10 |
-------     -------    ------

由于pointer1当前不在任何地方,因此您将遇到段错误。

如果您执行以下操作,这可能会起作用:

int **pointer1, *pointer2, value;
value = 10;
pointer2 = &value;
pointer1 = &pointer2;

在有两个“真实”代码段的情况下,第一段代码的问题是将未初始化的head传递给insert,然后随后取消引用head。这是与上述相同的问题。同样的事情在main中再次发生,因为在调用head之后list仍然是未初始化的,因为它是通过值传递的。第二段代码有效,因为您将head的地址传递给insert,因此随后对其取消引用是有效的。