如何在C中更改函数中的指针值

时间:2012-02-23 12:59:52

标签: c pointers pass-by-value

代码是:

     int main(int argc, const char* argv[] )
     {
        struct node * initialpointer=NULL;
        insert("asd", initialpointer, 1);
        if(initialpointer!=NULL)
            printf("isnotnull");
        if (initialpointer==NULL)
            printf("isnull");
     }
     insert(char* x,struct node * initialpointer, int numberofelements){
        struct node B;
        B.word = x;
        B.parent = NULL;
        B.leftchild = NULL;
        B.rightchild = NULL;
        printf("%d", 12);
        if ( initialpointer == NULL){
           initialpointer = &B;
           B.parent = NULL;
        }
     }

所以最后我希望initialpointer指向nde B的位置,但是在它打印的main方法中它是null。那么如何永久更改函数插入中的initialpointer

5 个答案:

答案 0 :(得分:4)

不要返回指向局部变量的指针,这将导致悬空指针:

struct node B;
...
initialpointer = &B;

你需要将一个指针传递给struct nodeinsert()malloc() struct node内的insert()指针:

insert(char* x,struct node ** initialpointer, int numberofelements)
{
    if (NULL == *initialpointer)
    {
        *initialpointer = malloc(sizeof(struct node));
        if (*initialpointer)
        {
            /* Note: you should probably make a copy of 'x',
               using 'strdup()' or similar, otherwise there
               is requiremenet that 'x' exist for the lifetime
               of '*initialpointer': which would be error prone. */
            (*initialpointer)->word       = x;
            (*initialpointer)->parent     = NULL;
            (*initialpointer)->leftchild  = NULL;
            (*initialpointer)->rightchild = NULL;
        }
    }
}

这保留了原始insert()的逻辑,因为node只应创建initialpointer initialpointer NULL。{/ p} >

并调用它:

struct node * initialpointer=NULL;
insert("asd", &initialpointer, 1);

不再需要时记住free()

free(initialpointer);

答案 1 :(得分:0)

struct node * initialpointer=NULL;
insert("asd", &initialpointer, 1);
...
void insert(char* x,struct node ** initialpointer, int numberofelements){
...
if ( *initialpointer == NULL){
    *initialpointer = &B;

但请记住,这也不适用于您当前的B自动(本地)变量。

您必须malloc() B

您在else声明中缺少if分支。

答案 2 :(得分:0)

根据@Paul Mitchell的评论编辑。

 int main(int argc, const char* argv[] )
 {
    struct node* initialpointer = insert("asd");
    if ( initialpointer == NULL )
       /* handle the error */

    /* remember to free() all the allocated nodes */
 }


 struct node* insert(char* x)
 {
    struct node* initialpointer = (struct node*)malloc(sizeof(struct node));
    if ( initialpointer == NULL)
        return NULL;  

    initialpointer.word = x;
    initialpointer.parent = NULL;
    initialpointer.leftchild = NULL;
    initialpointer.rightchild = NULL;
    return initialpointer;
 }

这将分配一个单个节点(我删除了numberofelements参数)。

要为多个节点分配空间,必须将指针传递给指针。但是,如果我了解您的意图,您希望节点成为链接结构的一部分,也许是树,因此您不需要为节点创建容器,因为您可以遍历结构以访问节点。

答案 3 :(得分:0)

您的代码存在一些问题。

首先是你遇到的问题。您传递给insert的指针是通过副本传递的;该函数获取副本,main没有看到您的更改。解决方法是将指针传递给指针。有关其外观的标准库示例,请参阅POSIX函数strtol

第二个问题是你返回一个指向本地自动(即堆栈分配)变量的指针。由于堆栈在函数退出时被释放,因此当指针返回main时,该指针指向无效内存。因此,您需要从堆中分配B

所以,解决问题:

 int main(int argc, const char* argv[] )
 {
    struct node * initialpointer=NULL;
    insert("asd", &initialpointer, 1);
    if(initialpointer!=NULL)
        printf("isnotnull");
    if (initialpointer==NULL)
        printf("isnull");
 }
 insert(char* x,struct node ** initialpointer, int numberofelements){
    struct node *B;
    B = (struct node*)malloc(sizeof(struct node));
    B->word = x;
    B->parent = NULL;
    B->leftchild = NULL;
    B->rightchild = NULL;
    printf("%d", 12);
    if ( *initialpointer == NULL){
       *initialpointer = B;
       B->parent = NULL;
    }
 }

答案 4 :(得分:0)

这有两个原因。

首先,您要更改局部范围变量,因为initialpointer是函数的参数。这意味着,无论其类型如何,您对变量本身所写的内容仅在insert函数内可见。如果你写的是*initialpointer那将是完全不同的故事。

现在,更有问题的是B是一个位于函数内部堆栈的局部变量。保留该功能后,B的存储位置将无效。因此,如果您将指针返回B,则访问insert之外的该对象将调用未定义的行为并且很可能无法正常工作(您很难有机会位置没有被改变,但那是纯粹的运气)。

你可能想要什么而不是

initialpointer = &B;

就是这样:

*initialpointer = B;

这会将B对象复制到指针变量引用的存储位置。现在B可以超出范围,因为您将所有内容复制到位于 main 内的initialpointer变量。

请注意,initialpointer中的main变量与insert中的变量完全不同!


最后一点,给出以大写字母开头的变量名称在我到目前为止遇到的任何命名方案中无效。