In your header, you declared point_t to be an opaque pointer type. This means that you only say that it is a pointer type such that a pointer of this type points to a struct point, but the definition of struct point is not provided. Therefore, a pointer of this type cannot be dereferenced without separately providing the definition of struct point. Rather, you probably should have written:
Code:
#ifndef EP_POINT_H_
#define EP_POINT_H_
struct point {
int x;
int y;
};
struct point *create_point(void);
#endif
Notice that:
- I included the header inclusion guards, without which including point.h twice in the same translation unit (source file + headers) would result in a multiple definition of struct point, which would be an error.
- I got rid of point_t. Unless you want to go with an opaque pointer, explicitly having the pointer notation is better as it reminds the reader that a pointer that can be dereferenced is involved.
- I explicitly used void as the parameter list for the declaration of create_point. Without this, the declaration says nothing about the parameters of create_point.
In your source files, you should #include "point.h", not <point.h>. The latter is generally for standard headers, other headers provided by the implementation, and headers from external libraries that you installed.
Of course, you might decide that you actually do want an opaque pointer. If so, you could do something like this:
Code:
#ifndef EP_POINT_H_
#define EP_POINT_H_
typedef struct point* point_t;
point_t point_create(void);
void point_destroy(point_t point);
int point_get_x(point_t point);
int point_get_y(point_t point);
#endif
Then in the source file:
Code:
#include "point.h"
struct point {
int x;
int y;
};
/* ... */
int point_get_x(point_t point) {
return point->x;
}
Now, you could write:
Code:
#include <stdio.h>
#include "point.h"
int main(void) {
point_t my_point = point_create();
printf("%d\n", point_get_x(my_point));
point_destroy(my_point);
return 0;
}
The dereferencing happens in point_get_x. At that point, the definition of struct point is available, so there is no incomplete type error. The useful part of doing this is that it means that at some later date, you could change the definition of struct point, e.g., rename x to x_coordinate, and the code in main does not need to change.