Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/64.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
c中使用结构指针的奇怪问题_C_Struct_Pass By Reference - Fatal编程技术网

c中使用结构指针的奇怪问题

c中使用结构指针的奇怪问题,c,struct,pass-by-reference,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; wal

好的,我对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'

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

您正在堆栈上创建struct对象。您需要使用

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


您正在创建内存泄漏!将&walker分配给指针时,将新内存分配给*指针,并丢失指针。

您的
init\u walker
错误,因为它返回指向堆栈局部变量
walker
的指针。一旦
init\u walker
退出,该变量的内存就会被回收。您的第一个
printf
仍然工作,这有点意外,因为
walker
变量的值在堆栈上仍然没有被触及。然而,一旦您在此之后进行任何函数调用,原始
init_walker
调用的堆栈帧就会被覆盖,
walker
指针现在指向一些随机垃圾

当您在
init\u walker
内部
malloc
时,您已经在堆上为
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;
}
但它可以更简单:

walker_t* init_walker(int x, int y) {

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

问题是您的
walker
指针指向无效的堆栈内存,因为
init\u walker
有一个bug:您在堆栈上创建一个
walker\u t
结构,然后使用
malloc
保留内存,并将该内存的地址分配给
pointer
。到目前为止还不错

但是,行
pointer=&walker
不会将结构从堆栈复制到新内存,而是使
pointer
指向堆栈上的结构
&walker
walker
的地址,您可以将其分配给指针。您可能要做的是复制结构。为此,必须取消对指针的引用:

*指针=walker

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

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

你的密码是“非常奇怪”

这将更好地工作

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);
}

然后,当您使用完它们后,请致电免费(walker)。

…或者,在检查代码是否正确后,您还可以编写:

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);

内存泄漏是另一个问题,您的解决方案无法解决它。您正在修复的问题是取消对悬挂引用的引用,而不是内存泄漏!你说得对!这很有效。虽然我仍然不完全理解问题是什么,因为第一个printf语句可以工作,但是指针一传递到函数就不能了。@icepack抱歉,我不明白你的意思。。。我将内存分配给一个新对象,超出此范围的内容在此函数中并不重要。@user1666419它首先起作用,因为您指向的内存仍然具有堆栈分配的值。内存不再有效,但其他任何东西都不需要它,因此它不会被覆盖。但是,一旦调用该函数,它将设置自己的堆栈框架,这将覆盖您的结构。@icepack不完全如此。init函数返回用户使用后需要释放的指针是正常的。但是,如果在malloc之后直接覆盖指针,就失去了释放内存的机会。您有一个输入错误;-)更改指针=&walker;对于*指针=步行器;为什么您决定对此使用动态内存分配?为什么要强制转换malloc的结果?我想知道原因。因为如果编译代码时,编译器警告很多(这是一件很好的事情),或者编译成C++,你会得到一个警告——关于将空隙*转换为Walkurt**的错误。编译器警告是您的朋友,请启用它们。在C中,对于任何体面的编译器上的void指针的隐式强制转换,您不会得到任何编译器警告。例如,尝试删除强制转换并使用
gcc-std=c99-Wall-Wextra-pedantic
编译。相反,您的类型转换隐藏了有用的警告,这是危险的。也。在C++中,你不应该使用MALOC,它是。所以请把你的答案中的类型转换掉,因为这是C标记。
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);
}
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);