I'm doing inheritance ( i.e. calling super class's function with subclass data type) with C, but encountered the aliasing issue.
In below, shape
function is called with rectangle
object.
In the case of me->super
, the x
and y
are correct. However, they're wrong in that of (Shape*)me
.
The reason I prefer (Shape*)me
over me->super
is that I want to hide struct implementation from clients.
Shouldn't C standard guarantee that? As per Section 6.7.2.1.13
“… A pointer to a structure object, suitably converted, points to its initial member. There may be unnamed padding within a structure object, but not at its beginning”.
/*shape.h*/
#ifndef SHAPE_H
#define SHAPE_H
typedef struct Shape Shape;
Shape* Shape_ctor(int x, int y);
int Shape_getX(Shape* me);
int Shape_getY(Shape* me);
#endif
/*shape.c*/
#include <stdlib.h>
#include "shape.h"
struct Shape
{
int x;
int y;
};
Shape* Shape_ctor(int x, int y)
{
Shape* me = malloc(sizeof(struct Shape));
me->x = x;
me->y = y;
return me;
}
int Shape_getX(Shape* me)
{
return me->x;
}
int Shape_getY(Shape* me)
{
return me->y;
}
/*rectangle.h*/
#ifndef RECT_H
#define RECT_H
#include "shape.h"
typedef struct Rectangle Rectangle;
Rectangle* Rectangle_ctor(int x, int y, unsigned int width, unsigned int height);
int Rectangle_getWidth(Rectangle* me);
int Rectangle_getHeight(Rectangle* me);
#endif
/*rectangle.c*/
#include <stdlib.h>
#include "rectangle.h"
#include "stdio.h"
struct Rectangle
{
Shape* super;
unsigned int width;
unsigned int height;
};
Rectangle* Rectangle_ctor(int x, int y, unsigned int width, unsigned int height)
{
Rectangle* me = malloc(sizeof(struct Rectangle));
me->super = Shape_ctor(x, y);
me->width = width;
me->height = height;
printf("x: %d\n", Shape_getX(me->super)); //correct value
printf("y: %d\n", Shape_getY(me->super)); //correct value
printf("x: %d\n", Shape_getX((Shape*)me)); // wrong value
printf("y: %d\n", Shape_getY((Shape*)me)); // wrong value
return me;
}
int Rectangle_getWidth(Rectangle* me)
{
return me->width;
}
int Rectangle_getHeight(Rectangle* me)
{
return me->height;
}
/*main.c*/
#include <stdio.h>
#include "rectangle.h"
int main(void) {
Rectangle* r1 = Rectangle_ctor(0, 2, 10, 15);
printf("r1: (x=%d, y=%d, width=%d, height=%d)\n", Shape_getX((Shape*)r1)
, Shape_getY((Shape*)r1)
, Rectangle_getWidth(r1)
, Rectangle_getHeight(r1));
return 0;
}