1

I have read the book Understanding and Using C Pointers and try to compile the code below. But after compiling I got the warning: assignment from incompatible pointer type.

I have checked the code and find out the function pointer fptrSet and function ShapeSetX is incompatible because the first argument of fptrSet is void * and function ShapeSetX is Shape *.

How can I fix this? Thanks!

typedef void (*fptrSet)(void*, int);
typedef int  (*fptrGet)(void*);
typedef void (*fptrDisplay)();    

typedef struct _vfunc
{
    fptrSet     setX;
    fptrGet     getX;
    fptrSet     setY;
    fptrGet     getY;
    fptrDisplay display;    
} vFunc;    

typedef struct _shape
{
    vFunc function;
    int x;
    int y;
} Shape;

void displayShape(){
    printf("Shape\n");
}
void ShapeSetX(Shape *shape, int x){
    shape->x = x;
}
void ShapeSetY(Shape *shape, int y){
    shape->y = y;
}
int ShapeGetX(Shape *shape){
    return shape->x;
}
int ShapeGetY(Shape *shape){
    return shape->y;
}    

Shape *newShape()
{
    Shape *shape = (Shape *)malloc(sizeof(Shape));
    shape->x = 10;
    shape->y = 10;
    shape->function.setX = ShapeSetX;
    shape->function.getX = ShapeGetX;
    shape->function.setY = ShapeSetY;
    shape->function.getY = ShapeGetY;
    shape->function.display = displayShape;
    return shape;
}
4
  • I think you can also change the typedef void (*fptrSet)(void*, int) to typedef void (*fptrSet)(Shape*, int) and the same for fptrGet. Commented Jun 14, 2016 at 10:49
  • @KevinWallis I think he wants something like virtual table from C++, so because there are no inheritance in C, he has to use void to allow "derived" struct from Shape Commented Jun 14, 2016 at 10:51
  • @KevinWallis @Garf365 is right, as you see this code is try to simulate the vtable from C++, so the the argument must be void * Commented Jun 15, 2016 at 3:33
  • Also : take a look at stackoverflow.com/questions/605845/… Commented Jun 15, 2016 at 7:16

2 Answers 2

1

You have to respect pointer definition: pointer need that first parameter is a pointer to void, so your function implementation should have first parameter as void:

void ShapeSetX(void *void_shape, int x){
    Shape *shape = (Shape*) void_shape;
    shape->x = x;
}
void ShapeSetY(void *void_shape, int y){
    Shape *shape = (Shape*) void_shape;
    shape->y = y;
}
int ShapeGetX(void *void_shape){
    Shape *shape = (Shape*) void_shape;
    return shape->x;
}
int ShapeGetY(void *void_shape){
    Shape *shape = (Shape*) void_shape;
    return shape->y;
} 
Sign up to request clarification or add additional context in comments.

2 Comments

@Garf365 Thanks for you answer and you got what I want. I try to use the code to simulate the 'ploymorphism' from OOP. Really thank you !
@FatMouse I think you have also to pass by a base structure, common on each instance (to access safetly to vtable). And also, in C++, vtable are static, you only store pointer to vtable in your instance. I try something to implements vtable here : ideone.com/P8dk6g any comments will be appreciate ;)
1

I was going to say "Why don't you replace void with Shape then?", until I realised that Shape hadn't been defined yet - nor could you swap the two definitions, because Shape needs vFunc which needs the typedefs.

So, do this:

typedef struct _shape Shape; // Define _shape and Shape later

typedef void (*fptrSet)(Shape*, int);
typedef int  (*fptrGet)(Shape*);
typedef void (*fptrDisplay)();    

If your compiler doesn't like that, you may need to change it to:

typedef struct _shape; // Define _shape later

typedef void (*fptrSet)(struct _shape*, int);
typedef int  (*fptrGet)(struct _shape*);
typedef void (*fptrDisplay)();    

4 Comments

With this solution, you can use _vfunc with other structure than Shape. I think OP wants a solution to have "inheritance" solution in C
For example with a function int getXOfInstance(void * instance, vFunc * vfunc) { return vfund->getX(instance);}
@Garf I thought of that - but with names like set/get' 'X/y and Display it all sounded rather "Shape-y"
It's not necessarily a Shape, it can be anything which have X, Y properties

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.