从结构体中的函数指针访问数据成员

huangapple go评论79阅读模式
英文:

Access data member from function pointer in struct

问题

I lack experience with C, and I'm not sure how to implement a function for a struct in C that can access and modify the struct's members like in C++.

英文:

I gotta admit. I lack experience with C and therefore I am unsure how to implement a function for a struct. There are plenty of answers out there: https://stackoverflow.com/questions/9871119/define-functions-in-structs, https://stackoverflow.com/questions/12642830/can-i-define-a-function-inside-a-c-structure, https://stackoverflow.com/questions/17052443/c-function-inside-struct, but they don't answer the result I am looking for. Now what I want is the following:

Imagine I have a struct like this:

typedef struct Ball {
  float x, y;
  float speedX, speedY;
  float radius;
  void (*Draw)();
} Ball;

Now I want the Draw fuction to be able to access the members of the Ball variable, as if I had an instance of a struct in C++. The function should be able to access the variables and modify them as much as I want it to. Is this even possible?

I tried some ridiculous stuff like this, but that didn't lead anywhere.

typedef struct Ball {
  float x, y;
  float speedX, speedY;
  float radius;
  void (*Draw)();
} Ball;

void Draw(float *x, float *y, float *speedX, float *speedY, float *radius) {
  DrawCircle((int)*x, (int)*y, (int)*radius, WHITE);
}

Here the C++ equivilant:

    struct Ball {
        float x{}, y{};
        float speedX{}, speedY{};
        float radius{};
        void Draw() {
            DrawCircle((int)x, (int)y, (int)radius, WHITE); //I know I could static_cast, but who cares :)
        }
    };
int main(int argc, char ** argv) {
    Ball ball;
    ball.x = 100.f;
   ...
    ball.Draw();
}

As you can see, the C++-way is pretty darn simple, I just couldn't figure it out for C.

答案1

得分: 3

只需以以下方式声明函数指针:

typedef struct Ball {
  float x, y;
  float speedX, speedY;
  float radius;
  void (*Draw)( struct Ball * );
} Ball;

当调用函数时,将一个指向结构类型对象的指针传递给它。

例如:

Ball ball = { /* 结构数据成员的初始化 */ };

ball.Draw( &ball );

函数可以实现如下,例如:

void Draw( struct Ball *ball ) 
{
    DrawCircle( ball->x, ball->y, ball->radius, WHITE );
}

并且可以像这样为结构类型对象的数据成员Draw分配函数:

ball.Draw = Draw;

或者,您可以声明函数DrawCircle,如下所示:

void DrawCircle( struct Ball *ball );

前提是它仅用于struct Ball类型的对象。然后,可以直接初始化数据成员Draw为此函数:

ball.Draw = DrawCircle;
英文:

Just declare the pointer to function the following way

typedef struct Ball {
  float x, y;
  float speedX, speedY;
  float radius;
  void (*Draw)( struct Ball * );
} Ball;

When the function will be called pass to it a pointer to an object of the structure type.

For example

Ball ball = { /* initializers of data members of the structure */ };

ball.Draw( &ball );

The function can be implemented for example like

void Draw( struct Ball *ball ) 
{
    DrawCircle( ball->x, ball->y, ball->radius, WHITE );
}

and the data member Draw of an object of the structure type can be assigned like

ball.Draw = Draw;

Or you could declare the function DrawCircle like

void DrawCircle( struct Ball *ball );

provided that it is used only for objects of the type struct Ball.

And directly initialize the data member Draw with this function

ball.Draw = DrawCircle;

答案2

得分: 0

如果您的所有Ball结构共享相同的Draw函数,那么在结构中存储该函数的函数指针是没有必要的,这是对内存的无意义浪费,也会不必要地增加复杂性。

只需将每个Ball独有的信息存储在结构中:

typedef struct Ball {
  float x, y;
  float speedX, speedY;
  float radius;
  // void (*Draw)(); 这不是必要的!
} Ball;

然后创建一个绘制球的函数:

void draw_a_ball(Ball *ball) {
  DrawCircle((int)ball->x, (int)ball->y, (int)ball->radius, WHITE);
}

然后您可以这样使用:

int main(int argc, char ** argv) {
    Ball ball;
    ball.x = 100.f;
    ...
    draw_a_ball(&ball);
}
英文:

If all of your Ball structures share the same Draw function, then there is no need to store a function pointer to that function in the structure. This is a pointless waste of memory and complicates things needlessly.

Just have the information that is unique to each Ball stored in the structure:

typedef struct Ball {
  float x, y;
  float speedX, speedY;
  float radius;
  // void (*Draw)(); No need for this!
} Ball;

And make a function that draws a ball:

void draw_a_ball(Ball *ball) {
  DrawCircle((int)Ball->x, (int)Ball->y, (int)Ball->radius, WHITE);
}

Then you can have:

int main(int argc, char ** argv) {
    Ball ball;
    ball.x = 100.f;
    ...
    draw_a_ball(&ball);
}

huangapple
  • 本文由 发表于 2023年6月1日 04:59:05
  • 转载请务必保留本文链接:https://go.coder-hub.com/76377225.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定