Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/59.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_Pointers_Struct - Fatal编程技术网

C 使用带指针的结构时出现问题

C 使用带指针的结构时出现问题,c,pointers,struct,C,Pointers,Struct,我试着让一个球在球场上左右反弹。如果我打印普通结构并通过函数传递所述结构的指针,我就可以使其正常工作 当我运行下面的代码时,它会打印我认为是structs元素的内存地址,而不是这些地址中包含的实际值。我不明白的是为什么第一段代码不起作用,而第二段却起作用。我很确定我把指针弄乱了,但我不知道在哪里 坏代码 typedef struct Ball ball; int width=80, height=20; //screen height/width in characters struct B

我试着让一个球在球场上左右反弹。如果我打印普通结构并通过函数传递所述结构的指针,我就可以使其正常工作

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

坏代码

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结构球;
内部宽度=80,高度=20//屏幕高度/宽度(字符)
结构球{
炭状;
int x;
int-y;
int velX;
内在的;
};
ball*initBall(整数X,整数Y,整数velx,整数vely,字符形状){
球b;
球*p=&b;
p->x=x;
p->y=y;
p->fly=fly;
p->velX=velX;
p->shape=shape;
返回p;
}
无效移动球(球*b){
如果(b->x+b->velX>width | b->x+b->velX<0){
b->velX*=-1;
}
如果(b->y+b->Fly>高度| b->y+b->Fly<0){
b->fly*=-1;
}
b->x+=b->velX;
b->y+=b->y;
}
int main(){
ball*p=initBall(40,10,1,0,'O');
int计数器=0;
while(计数器<10){
printf(“%d,%d\n”,p->x,p->y);
moveBall(p);
计数器++;
}
返回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;
}
typedef结构球;
内部宽度=80,高度=20//屏幕高度/宽度(字符)
结构球{
炭状;
int x;
int-y;
int velX;
内在的;
};
ball initBall(int X,int Y,int velx,int vely,char shape){
球b;
球*p=&b;
b、 x=x;
b、 y=y;
b、 弗利=弗利;
b、 velX=velX;
b、 形状=形状;
返回b;
}
无效移动球(球*b){
如果(b->x+b->velX>width | b->x+b->velX<0){
b->velX*=-1;
}
如果(b->y+b->Fly>高度| b->y+b->Fly<0){
b->fly*=-1;
}
b->x+=b->velX;
b->y+=b->y;
}
int main(){
球b=初始球(40,10,1,0,'O');
球*p=&b;
int计数器=0;
while(计数器<10){
printf(“%d,%d\n”,p->x,p->y);
moveBall(p);
计数器++;
}
返回0;
}

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


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

您返回的是一个局部变量的地址,由于变量所在的函数退出,该地址立即变得无效

不要这样做,这不是有效代码

您必须使分配
为静态
,或者使用
malloc()
来分配不超出范围的堆内存

这:

应该是:

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

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

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

initBall()的错误代码中。

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

在良好代码中,您将结构作为值返回,因此值将复制到
main()

解决办法是:

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

    ...
    return p;
}

完成后别忘了
free()
将其释放。

如果您在编译时启用了警告,您将得到如下警告:
“警告:返回局部变量的地址”
。。。这应该是个好消息。
ball* initBall(int X, int Y, int velx, int vely, char shape){
    ball b;
    ball *p = &b;
    ...
    return p;
}
ball* initBall(int X, int Y, int velx, int vely, char shape){
    ball b;
    ball *p = malloc(sizeo(*p));

    ...
    return p;
}