使用带指针的结构的问题

时间:2013-11-01 09:03:38

标签: c pointers struct

我试图在ncurses中将球反弹到一边。如果我打印普通的struct并通过函数传递所述struct的指针,我可以正常工作。

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

糟糕的代码,

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 个答案:

答案 0 :(得分:1)

在错误代码中,您将返回指向initBall内的局部变量的指针。从initBall返回后,此指针将无效,并且当您调用另一个函数时,该结构的内容很可能会被其他数据覆盖。

在优秀的代码中,你没有返回指向struct的指针,你要返回整个结构 - 也就是结构的副本,所以这不是问题。如果你不介意在返回时复制整个结构,那么坚持使用好的代码(这可能是低效的);否则,使用动态内存分配。

答案 1 :(得分: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()

答案 2 :(得分:0)

当您返回指向局部变量的指针时,initBall中有未定义的行为。请记住,变量b的范围以函数结束,因此在函数返回之后,指向它的指针不再有效。

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

答案 3 :(得分: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;
}