在c中使用struct指针的奇怪问题

时间:2013-02-19 11:43:11

标签: c struct pass-by-reference

好的,所以我对c中的结构都是全新的,我有一个对我来说很奇怪的问题。
当使用它的指针将一个简单的结构传递给一个函数时,该结构会自动将该函数的其他参数之一作为它的新数据。我不知道为什么会发生这种情况.. 此时move_walker()应该什么都不做,对吧?

typedef struct {
    int x,
        y;
} walker_t;

walker_t* init_walker(int x, int y) {
    walker_t walker;
    walker.x = x;
    walker.y = y;
    walker_t *pointer = malloc(sizeof(walker));
    pointer = &walker;
    return pointer;
}

int move_walker(walker_t * walker, int direction) {
    return 0;
}

walker_t* walker;
walker = init_walker(8,2);

printf("%d %d\n", walker->x, walker->y); //will print '8 2'
move_walker(walker, 3);
printf("%d %d\n", walker->x, walker->y); //will print '0 3'

(我很确定它并不重要,但这段代码实际上是在多个文件上传播的。)

6 个答案:

答案 0 :(得分:3)

您的init_walker错误,因为它返回指向堆栈局部变量walker的指针。 init_walker退出后,该变量的内存将被回收。您的第一个printf仍然可以正常工作,因为您的walker变量的值在堆栈中仍未触及。但是,只要在此之后进行任何函数调用,原始init_walker调用的堆栈帧就会被覆盖,而walker指针现在指向一些随机垃圾。

当您mallocinit_walker时,您已经在堆上分配内存(与堆栈不同,它超出了堆栈帧的生命周期)walker_t。所以,你应该这样做:

walker_t* init_walker(int x, int y) {
    walker_t *pointer = malloc(sizeof(walker_t));
    pointer->x = x;
    pointer->y = y;
    return pointer;
}

答案 1 :(得分:3)

问题是你的walker指针转到了无效的堆栈内存,因为init_walker有一个错误:你在堆栈上创建一个walker_t结构,然后使用{{1保留内存并将该内存的地址分配给malloc。到目前为止一切都很好。

但是,行pointer 将结构从堆栈复制到新内存,而是使pointer = &walker指向堆栈上的结构! pointer&walker的地址,您可以将其指定给指针。你可能想要做的是复制结构。要做到这一点,你必须取消引用你的指针:

walker

这应该使您的程序按预期工作。您也可以完全跳过堆栈上的结构:

*pointer = walker

答案 2 :(得分:2)

您正在堆栈上创建struct-object。您需要使用

分配它
walker_t* init_walker(int x, int y) {
walker_t* walker = malloc(sizeof(walker_t));
...
return walker;
}

使用

walker_t *pointer = malloc(sizeof(walker));
pointer = &walker;

你正在创造一个内存泄漏!将新内存分配给*指针并在将& walker指定给指针时丢失指针。

答案 3 :(得分:0)

 walker_t* init_walker(int x, int y) {
    walker_t walker;
    walker.x = x;
    walker.y = y;
    walker_t *pointer = malloc(sizeof(walker));
    *pointer = walker;  /* here was the error. Copy the value not the adress */
    return pointer;
}

但它可以更简单:

walker_t* init_walker(int x, int y) {

    walker_t *pointer = malloc(sizeof(*pointer));
    pointer->x = x;
    pointer->y = y;       
    return pointer;
}

答案 4 :(得分:0)

你的代码就是把政治变得“非常奇怪”。

这会更好......

walker_t *init_walker (int x, int y)
{
    walker_t *p_walker = (walker_t *)malloc (sizeof(walker));

    if (p_walker != NULL)
    {
        p_walker->x = x;
        p_walker->y = y;
    }
    return (p_walker);
}

然后在完成后调用free (walker)

答案 5 :(得分:0)

......或者,在对代码进行完整性检查之后,您还可以写下:

typedef struct 
{
    int x,
    int y;
} walker_t;

void init_walker(walker_t* obj, int x, int y) 
{
   obj->x = x;
   obj->y = y;
}

walker_t walker;
init_walker(&walker, 8,2);