Объявление и инициализация

Интерфейсы

//C has no interfaces: a table of pointers to functions plays one
typedef struct Shape Shape;

//the interface: what every shape can do
struct ShapeOps {
    const char *name;
    double (*area)(const Shape *self);
    void (*scale)(Shape *self, double factor);
};

//an object keeps only a pointer to the table of its type:
//the table is one for all objects and never changes
struct Shape {
    const struct ShapeOps *ops;
};

//the only implementation of the interface
typedef struct {
    Shape base;
    double width, height;
} Rect;

double rectArea(const Shape *self) {
    const Rect *rect = (const Rect *)self;
    return rect->width * rect->height;
}

void rectScale(Shape *self, double factor) {
    Rect *rect = (Rect *)self;
    rect->width *= factor;
    rect->height *= factor;
}

const struct ShapeOps rectOps = {"rect", rectArea, rectScale};

Rect rect = {{&rectOps}, 2, 3};

//the code below sees only Shape and its table
Shape *shape = &rect.base;
double area1 = shape->ops->area(shape);
//area1 is 6
shape->ops->scale(shape, 2);
double area2 = shape->ops->area(shape);
//area2 is 24
const char *name = shape->ops->name;
//name is "rect"

//the table may grow, the object still holds one pointer
bool onePointer = sizeof(Shape) == sizeof(void *);
//onePointer is true

printf("area1 is %g\n", area1);
printf("area2 is %g\n", area2);
printf("name is %s\n", name);
printf("onePointer is %s\n", onePointer ? "true" : "false");