0

我试图让球在 ncurses 中左右弹跳。如果我打印普通结构并通过函数传递所述结构的指针,我可以让它正常工作。

当我运行以下代码时,它会打印我认为是结构元素的内存地址,而不是这些地址中包含的实际值。我不明白为什么第一段代码不起作用,但第二段代码起作用。我很确定我搞砸了指针,但我不知道在哪里。

糟糕的代码,

typedef struct Ball ball;

int width=80, height=20; //screen height/width in characters

struct Ball{
    char shape;
    int x;
    int y;
    int velX; 
    int velY;
};

ball* initBall(int X, int Y, int velx, int vely, char shape){
    ball b;
    ball *p = &b;
    p->x = X;
    p->y = Y;
    p->velY = vely;
    p->velX = velx;
    p->shape = shape;

    return p;
}

void moveBall(ball *b){
    if(b->x +b->velX > width || b->x + b->velX < 0){
        b->velX *= -1;
    }

    if(b->y +b->velY > height || b->y +b->velY< 0){
        b->velY *= -1;
    }

    b->x += b->velX;
    b->y += b->velY;
}

int main(){
    ball *p = initBall(40,10,1,0, 'O');

    int counter=0;
    while(counter < 10){
        printf("%d, %d\n", p->x, p->y);

        moveBall(p);

        counter++;
    }

    return 0;
}

好的代码,

typedef struct Ball ball;

int width=80, height=20; //screen height/width in characters

struct Ball{
    char shape;
    int x;
    int y;
    int velX; 
    int velY;
};

ball initBall(int X, int Y, int velx, int vely, char shape){
    ball b;
    ball *p = &b;
    b.x = X;
    b.y = Y;
    b.velY = vely;
    b.velX = velx;
    b.shape = shape;

    return b;
}

void moveBall(ball *b){
    if(b->x +b->velX > width || b->x + b->velX < 0){
        b->velX *= -1;
    }

    if(b->y +b->velY > height || b->y +b->velY< 0){
        b->velY *= -1;
    }

    b->x += b->velX;
    b->y += b->velY;
}

int main(){
    ball b = initBall(40,10,1,0, 'O');
    ball *p = &b;

    int counter=0;
    while(counter < 10){
        printf("%d, %d\n", p->x, p->y);

        moveBall(p);

        counter++;
    }

    return 0;
}
4

4 回答 4

1

在糟糕的代码中,您将返回一个指向内部局部变量的指针initBall。一旦你从 中返回,这个指针就会失效initBall,并且当你调用另一个函数时,结构的内容很可能会被其他数据覆盖。

在好的代码中,您不会返回指向结构的指针,而是返回整个结构 - 即结构的副本,所以这不是问题。如果您不介意在返回时复制整个结构(这可能效率低下),请坚持使用好的代码;否则,使用动态内存分配。

于 2013-11-01T09:07:05.320 回答
1

错误的代码initBall()

ball* initBall(int X, int Y, int velx, int vely, char shape){
    ball b;
    ball *p = &b;
    ...
    return p;
}

您正在返回局部变量的地址,这是不正确的。一旦函数返回,该内存位置的内容就会改变。

良好的代码中,您将结构作为值返回,因此这些值被复制到main().

解决方法是:

ball* initBall(int X, int Y, int velx, int vely, char shape){
    ball b;
    ball *p = malloc(sizeo(*p));

    ...
    return p;
}

完成后不要忘记free()它。

于 2013-11-01T09:08:56.070 回答
0

initBall当您返回指向局部变量的指针时,您有未定义的行为。记住变量的作用域b以函数结束,所以函数返回后指向它的指针不再有效。

您可能希望改为在堆上分配结构。

于 2013-11-01T09:06:28.150 回答
0

您正在返回一个局部变量的地址,然后由于该变量所在的函数退出,该地址立即变为无效。

不要这样做,它不是有效的代码。

您必须要么进行分配static,要么使用malloc()分配不会超出范围的堆内存。

这个:

ball* initBall(int X, int Y, int velx, int vely, char shape){
  ball b;
  ball *p = &b;

应该:

ball * initBall(int X, int Y, int velx, int vely, char shape){
  ball *b = malloc(sizeof *b);
  if(b != NULL) {
    b->x = X;
    /* and so on */
  }
  return b;
}
于 2013-11-01T09:06:34.307 回答