Is there a way to write OO-like code in the C programming language?
See also:
Can you write object-oriented code in C?
Object-orientation in C
Found by searching on "[c] oo".
The first C++ compiler ("C with classes") would actually generate C code, so that's definitely doable.
Basically, your base class is a struct; derived structs must include the base struct at the first position, so that a pointer to the "derived" struct will also be a valid pointer to the base struct.
typedef struct {
data member_x;
} base;
typedef struct {
struct base;
data member_y;
} derived;
void function_on_base(struct base * a); // here I can pass both pointers to derived and to base
void function_on_derived(struct derived * b); // here I must pass a pointer to the derived class
The functions can be part of the structure as function pointers, so that a syntax like p->call(p) becomes possible, but you still have to explicitly pass a pointer to the struct to the function itself.
Common approach is to define struct with pointers to functions. This defines 'methods' which can be called on any type. Subtypes then set their own functions in this common structure, and return it.
For example, in linux kernel, there is struct:
struct inode_operations {
int (*create) (struct inode *,struct dentry *,int, struct nameidata *);
struct dentry * (*lookup) (struct inode *,struct dentry *,
struct nameidata *);
...
};
Each registered type of filesystem then registers its own functions for create, lookup, and remaining functions. Rest of code can than use generic inode_operations:
struct inode_operations *i_op;
i_op -> create(...);
C++ is not that far from C.
Classes are structures with a hidden pointer to a table of function pointers called VTable. The Vtable itself is static.
When types point to Vtables with the same structure but where pointers point to other implementation, you get polymorphism.
It is recommended to encapsulate the calls logic in function that take the struct as parameter to avoid code clutter.
You should also encapsulcte structures instantiation and initialisation in functions (this is equivalent to a C++ constructor) and deletion (destructor in C++). These are good practice anyway.
typedef struct
{
int (*SomeFunction)(TheClass* this, int i);
void (*OtherFunction)(TheClass* this, char* c);
} VTable;
typedef struct
{
VTable* pVTable;
int member;
} TheClass;
To call the method:
int CallSomeFunction(TheClass* this, int i)
{
(this->pVTable->SomeFunction)(this, i);
}
I looked at everyone elses' answers and came up with this:
#include <stdio.h>
typedef struct
{
int (*get)(void* this);
void (*set)(void* this, int i);
int member;
} TheClass;
int Get(void* this)
{
TheClass* This = (TheClass*)this;
return This->member;
}
void Set(void* this, int i)
{
TheClass* This = (TheClass*)this;
This->member = i;
}
void init(TheClass* this)
{
this->get = &Get;
this->set = &Set;
}
int main(int argc, char **argv)
{
TheClass name;
init(&name);
(name.set)(&name, 10);
printf("%d\n", (name.get)(&name));
return 0;
}
I hope that answers some questions.
Appendix B of the article Open Reusable Object Models, by Ian Piumarta and Alessandro Warth of VPRI is an implementation of an Object model in GNU C, about 140 lines of code. It's a fascinating read !
Here's the uncached version of the macro that sends messages to objects, using a GNU extension to C (statement expression):
struct object;
typedef struct object *oop;
typedef oop *(*method_t)(oop receiver, ...);
//...
#define send(RCV, MSG, ARGS...) ({ \
oop r = (oop)(RCV); \
method_t method = _bind(r, (MSG)); \
method(r, ##ARGS); \
})
In the same doc, have a look at the object, vtable, vtable_delegated and symbol structs, and the _bind and vtable_lookup functions.
Cheers!
What I usually like to do is to wrap the structs in another which contain meta information about the wrapped class and then build visitor like function lists acting on the generic struct. The advantage of this approach is that you don't need to modify the existing structures and you can create visitors for any subset of structs.
Take the usual example:
typedef struct {
char call[7] = "MIAO!\n";
} Cat;
typedef struct {
char call[6] = "BAU!\n";
} Dog;
We can wrap the 2 strutures in this new structure:
typedef struct {
const void * animal;
AnimalType type;
} Animal;
The type can be a simple int but let's not be lazy:
typedef enum {
ANIMAL_CAT = 0,
ANIMAL_DOG,
ANIMAL_COUNT
} AnimalType;
It would be nice to have some wrapping functions:
Animal catAsAnimal(const Cat * c) {
return (Animal){(void *)c, ANIMAL_CAT};
}
Animal dogAsAnimal(const Dog * d) {
return (Animal){(void *)d, ANIMAL_DOG};
}
Now we can define our "visitor":
void catCall ( Animal a ) {
Cat * c = (Cat *)a.animal;
printf(c->call);
}
void dogCall ( Animal a ) {
Dog * d = (Dog *)a.animal;
printf(d->call);
}
void (*animalCalls[ANIMAL_COUNT])(Animal)={&catCall, &dogCall};
Then the actual usage will be:
Cat cat;
Dog dog;
Animal animals[2];
animals[0] = catAsAnimal(&cat);
animals[1] = dogAsAnimal(&dog);
for (int i = 0; i < 2; i++) {
Animal a = animals[i];
animalCalls[a.type](a);
}
The disadvantage of this approach is that you have to wrap the structures every time you want to use it as a generic type.
The file functions fopen, fclose, fread are examples of OO code in C. Instead of the private data in class, they work on the FILE structure which is used to encapsulate the data and the C functions acts as an member class functions.
http://www.amazon.com/File-Structures-Object-Oriented-Approach-C/dp/0201874016
#include <stdio.h>
typedef struct {
int x;
int z;
} base;
typedef struct {
base;
int y;
int x;
} derived;
void function_on_base( base * a) // here I can pass both pointers to derived and to base
{
printf("Class base [%d]\n",a->x);
printf("Class base [%d]\n",a->z);
}
void function_on_derived( derived * b) // here I must pass a pointer to the derived class
{
printf("Class derived [%d]\n",b->y);
printf("Class derived [%d]\n",b->x);
}
int main()
{
derived d;
base b;
printf("Teste de poliformismo\n");
b.x = 2;
d.y = 1;
b.z = 3;
d.x = 4;
function_on_base(&b);
function_on_base(&d);
function_on_derived(&b);
function_on_derived(&d);
return 0;
}
The output was:
Class base [3]
Class base [1]
Class base [4]
Class derived [2]
Class derived [3]
Class derived [1]
Class derived [4]
so it works, its a polymorphic code.
UncleZeiv explained about it at the beginning.
From Wikipedia:
In programming languages and type theory, polymorphism (from Greek πολύς, polys, "many, much" and μορφή, morphē, "form, shape") is the provision of a single interface to entities of different types.
So I would say the only way to implement it in C is by using variadic arguments along with some (semi)automatic type info management.
For example in C++ you can write (sorry for trivialness):
void add( int& result, int a1, int a2 );
void add( float& result, float a1, float a2 );
void add( double& result, double a1, double a2 );
In C, among other solutions, the best you can do is something like this:
int int_add( int a1, int a2 );
float float_add( float a1, fload a2 );
double double_add( double a1, double a2 );
void add( int typeinfo, void* result, ... );
Then you need:
to implement the "typeinfo" with enums/macros
to implement the latter function with stdarg.h stuff
to say goodbye to C static type checking
I am almost sure that any other implementation of polymorphism should look much like this very one.
The above answers, instead, seems to try to address inheritance more than polymorphism!
In order too build OO functionality in C, you can look at previous answers.
But, (as it has been asked in other questions redirected to this one) if you want to understand what polymorphism is, by examples in C language. Maybe I am wrong, but I can't think of anything as easy to understand as C pointers arithmetic. In my opinion, pointer arithmetic is inherently polymorphic in C. In the following example the same function (method in OO), namely the addition (+), will produce a different behavior depending on the properties of the input structures.
Example:
double a*;
char str*;
a=(double*)malloc(2*sizeof(double));
str=(char*)malloc(2*sizeof(char));
a=a+2; // make the pointer a, point 2*8 bytes ahead.
str=str+2; // make the pointer str, point 2*1 bytes ahead.
Disclaimer: I am very new at C and very much looking forward to being corrected and learn from other user's comments, or even completely erase this answer, should it be wrong. Many thanks,
A very crude example of simple function overloading, much can be achieved using variadic macros.
#include <stdio.h>
#include <stdlib.h>
#define SCOPE_EXIT(X) __attribute__((cleanup (X)))
struct A
{
int a;
};
struct B
{
int a, b;
};
typedef struct A * A_id;
typedef struct B * B_id;
A_id make_A()
{
return (A_id)malloc(sizeof(struct A));
}
void destroy_A(A_id * ptr)
{
free(*ptr);
*ptr = 0;
}
B_id make_B()
{
return (B_id)malloc(sizeof(struct B));
}
void destroy_B(B_id * ptr)
{
free(*ptr);
*ptr = 0;
}
void print_a(A_id ptr)
{
printf("print_a\n");
}
void print_b(B_id ptr)
{
printf("print_b\n");
}
#define print(X) _Generic((X),\
A_id : print_a, \
B_id : print_b\
)(X)
int main()
{
A_id aa SCOPE_EXIT(destroy_A) = make_A();
print(aa);
B_id bb SCOPE_EXIT(destroy_B) = make_B();
print(bb);
return 0;
}
Different implementations of functions is one of the key features of polymorphism, so you must use function pointers.
animal.h
typedef struct Animal {
const void (*jump)(struct Animal *self);
} Animal;
pig.h
#include "animal.h"
typedef struct {
Animal animal_interface;
char *name;
} Pig;
Pig *NewPig(char *name);
pig.c
#include <stdio.h>
#include <stdlib.h>
#include "pig.h"
static void PigJump(Animal *_self) {
Pig *self = (Pig *)_self;
printf("%s Pig jump.\n", self->name);
}
Pig *NewPig(char *name) {
Pig *self = (Pig *)malloc(sizeof(Pig));
self->animal_interface.jump = PigJump;
self->name = name;
return self;
}
main.c
#include "pig.h"
int main() {
Animal *a = &(NewPig("Peppa")->animal_interface);
Animal *b = &(NewPig("Daddy")->animal_interface);
a->jump(a);
b->jump(b);
return 0;
}
Output:
Peppa Pig jump.
Daddy Pig jump.
I have successfully achieved polymorphism in C so I felt like sharing my code. I have a struct Pas which "inherits" from struct Zivotinja (Pas means Dog, Zivotinja means Animal BTW).
In both Zivotinja and Pas the first field of the struct is the vTable.
Zivotinja has a vTable of the type ZivotinjaVTable, Pas has a vTable of the type PasVTable. So, we have
typedef struct ZivotinjaVTableStruct{
void (*ispisiPodatkeOZivotinji)(void *zivotinja);
int (*dajGodine) (void *zivotinja);
} ZivotinjaVTable;
typedef struct ZivotinjaStruct{
ZivotinjaVTable *vTable;
int godine;
} Zivotinja;
and we have
typedef struct PasVTableStruct{
void (*ispisiPodatkeOZivotinji)(void *Pas);
int (*dajGodine) (void *Pas);
bool (*daLiJeVlasnikStariji) (void *Pas);
} PasVTable;
typedef struct PasStruct{
PasVTable *vTable;
int godine;
const char* vlasnik;
int godineVlasnika;
} Pas;
Don't worry about the names of the functions, that's not relevant.
Anyway, I then wrote functions for both of these vTables. How did I connect the vTables with the functions that I wrote for them? I created a global struct both for the ZivotinjaVTable and for the PasVTable. I created vTableZivotinjaGlobal and vTablePasGlobal which have function pointers of the functions that I wrote. Then I created functions Pas_new() and Zivotinja_new() which initialize vTable fields to point to these global vTable structs.
Notice the important details in the code above. The important thing is that vTables are the first fields in their structs. That way, when we write
Zivotinja *z = (Zivotinja*) Pas_new(/* init variables */);
z->vTable->someMethod(z);
the compiler knows that vTable is the first field in the Zivotinja struct, so when compiler reads z->vTable, it will go to the memory address to which the first 8 bytes of your struct z point to (or first 4 bytes, if you have a 32bit PC, but that is irrelevant for the point that I am making).
This is how I tricked the computer, since this z pointer is actually pointing to a Pas struct and since PasVTable *vTable is the first field of the Pas struct, after z->vTable we will actually be at the memory address of the pasVTableGlobal, instead of being at the memory address of the zivotinjaVTableGlobal.
Now, another very important detail, someMethod needs to be at the same spot both in the ZivotinjaVTable and in the PasVTable. What I mean is - if someMethod is the 2nd field in the ZivotinjaVTable then it needs to be the second field of the PasVTable. Why?
Because let's say someMethod is the second field of the ZivotinjaVTable, when the compiler reads z->vTable->someMethod(z); computer will take the second 8 bytes in the memory address z->vTable and it will put those 8 bytes into the instruction pointer (or second 4 bytes if you have a 32 bit PC, but again, this is not relevant). Computer "thinks" it is putting the second 8 bytes of the ZivotinjaVTable into the instruction pointer, but in reality it is putting the second 8 bytes of the PasVTable into the instruction pointer.
This is how the trick works, because the function that we want the computer to execute is also the second field (but of the PasVTable, not ZivotinjaVTable), the computer will "think" that it is executing the second function of the ZivotinjaVTable, but in reality it will be executing the second function of the PasVTable.
So, to recapitulate, vTables should be on the same spot in your structs and your structs should have corresponding methods at the same spots in their vTables.
Same goes for other fields of your structs. The second field of the Zivotinja struct matches the second field of the Pas struct, that way when you write
animal_which_is_actually_a_dog->age = 10;
You will trick the compiler in basically the same way as with vTables (you will trick it in the same way that I have described above).
Here is the entire code, in the main function you can write the following
Zivotinja *zivotinja = Zivotinja_new(10);
zivotinja->vTable->ispisiPodatkeOZivotinji(zivotinja);
Zivotinja *pas = Pas_new_sve(5, 50, "Milojko");
pas->vTable->ispisiPodatkeOZivotinji(pas);
int godine = pas->vTable->dajGodine(pas);
printf("The dog which was casted to an animal is %d years old.\n", godine);
Then this is the code for Zivotinja
typedef struct ZivotinjaVTableStruct{
void (*ispisiPodatkeOZivotinji)(void *zivotinja);
int (*dajGodine) (void *zivotinja);
} ZivotinjaVTable;
typedef struct ZivotinjaStruct{
ZivotinjaVTable *vTable;
int godine;
} Zivotinja;
void ispisiPodatkeOOvojZivotinji(Zivotinja* zivotinja){
printf("Ova zivotinja ima %d godina. \n", zivotinja->godine);
}
int dajGodineOveZivotinje(Zivotinja *z){
return z->godine;
}
struct ZivotinjaVTableStruct zivotinjaVTableGlobal = {ispisiPodatkeOOvojZivotinji, dajGodineOveZivotinje};
Zivotinja* Zivotinja_new(int godine){
ZivotinjaVTable *vTable = &zivotinjaVTableGlobal;
Zivotinja *z = (Zivotinja*) malloc(sizeof(Zivotinja));
z->vTable = vTable;
z->godine = godine;
}
And finally, the code for Pas
typedef struct PasVTableStruct{
void (*ispisiPodatkeOZivotinji)(void *Pas);
int (*dajGodine) (void *Pas);
bool (*daLiJeVlasnikStariji) (void *Pas);
} PasVTable;
typedef struct PasStruct{
PasVTable *vTable;
int godine;
const char* vlasnik;
int godineVlasnika;
} Pas;
void ispisiPodatkeOPsu(void *pasVoid){
Pas *pas = (Pas*)pasVoid;
printf("Pas ima %d godina, vlasnik se zove %s, vlasnik ima %d godina. \n", pas->godine, pas->vlasnik, pas->godineVlasnika);
}
int dajGodinePsa(void *pasVoid){
Pas *pas = (Pas*) pasVoid;
return pas->godine;
}
bool daLiJeVlasnikStariji(Pas *pas){
return pas->godineVlasnika >= pas->godine;
}
struct PasVTableStruct pasVTableGlobal = {
ispisiPodatkeOPsu,
dajGodinePsa,
daLiJeVlasnikStariji
};
Pas* Pas_new(int godine){
Pas *z = (Pas*) malloc(sizeof(Pas));
z->vTable = (&pasVTableGlobal);
}
Pas *Pas_new_sve(int godine, int godineVlasnika, char* imeVlasnika){
Pas *pas = (Pas*) malloc(sizeof(Pas));
pas->godine = godine;
pas->godineVlasnika = godineVlasnika;
pas->vlasnik = imeVlasnika;
pas->vTable = &pasVTableGlobal;
}
Related
I'm trying to implement a struct person, and I need to hide some fields or make them constant.
A trick for create private fields.
Header:
#pragma once
#define NAME_MAX_LEN 20
typedef struct _person {
float wage;
int groupid;
} Person;
const char const *getName (Person *p);
int getId (Person *p);
/// OTHER FUNCTIONS
Source
#include "person.h"
struct _person
{
int id;
float wage;
int groupid;
char name[NAME_MAX_LEN];
};
/// FUNCTIONS
GCC says that person.c:7:8: error: redefinition a 'struct _person' struct _person
I can write this in a header, but after it, I can't use fields of a struct.
typedef struct _person Person;
A struct cannot have multiple conflicting definitions. As such, you can't create a struct that hides some of the fields.
What you can do however it declare that the struct exists in the header without defining it. Then the caller is restricted to using only a pointer to the struct and using functions in your implementation to modify it.
For example, you could define your header as follows:
typedef struct _person Person;
Person *init(const char *name, int id, float wage, int groupid);
const char *getName (const Person *p);
int getId (const Person *p);
float getWage (const Person *p);
int getGroupid (const Person *p);
And your implementation would contain:
#include "person.h"
struct _person
{
int id;
float wage;
int groupid;
char name[NAME_MAX_LEN];
};
Person *init(const char *name, int id, float wage, int groupid)
{
Person *p = malloc(sizeof *p);
strcpy(p->name, name);
p->id = id;
p->wage= wage;
p->groupid= groupid;
return p;
}
...
C has no mechanism for hiding individual members of a structure type. However, by operating only in terms of pointers to such a type, and not providing a definition, you can make the whole type opaque. Users would then have to use the functions you provide to manipulate instances in any way. This is a thing that is sometimes done.
To some extent, you may be able to achieve something like what you describe with a hidden context. For example, consider this:
header.h
typedef struct _person {
float wage;
int groupid;
} Person;
implementation.c
struct _person_real {
Person person; // must be first, and is a structure, not a pointer.
int id;
char name[NAME_MAX_LEN];
};
Now you can do this:
Person *create_person(char name[]) {
struct _person_real *pr = malloc(sizeof(*pr));
if (pr) {
pr->person.wage = DEFAULT_WAGE;
pr->person.groupid = DEFAULT_GROUPID;
pr->id = generate_id();
strncpy(pr->name, name, sizeof(pr->name));
pr->name[sizeof(pr->name) - 1] = '\0';
return &pr->person; // <-- NOTE WELL
} else {
return NULL;
}
}
A pointer to the first member of a structure always points also to the whole structure, too, so if the client passes a pointer obtained from that function back to you, you can
struct _person_real *pr = (struct _person_real *) Person_pointer;
and work on the members from the larger context.
Be well aware, however, that such a scheme is risky. Nothing prevents a user from creating a Person without the larger context, and passing a pointer to it to a function that expects the context object to be present. There are other issues.
Overall, C APIs generally either take the opaque structure approach or just carefully document what clients are permitted to do with the data they have access to, or even just document how everything works, so that users can make their own choices. These, especially the latter, are well aligned with overall C approaches and idioms -- C does not hold your hand, or protect you from doing harm. It trusts you to know what you're doing, and to do only what you intend to do.
You can use a mixin style; e.g. write in the header:
struct person {
float wage;
int groupid;
};
struct person *person_new(void);
char const *getName (struct person const *p);
int getId (struct person const *p);
and in the source
struct person_impl {
struct person p;
char name[NAME_MAX_LEN];
int id;
}
struct person *person_new(void)
{
struct person_impl *p;
p = malloc(sizeof *p);
...
return &p->p;
}
chra const *getName(struct person const *p_)
{
struct person_impl *p =
container_of(p_, struct person_impl, p);
return p->name;
}
See e.g. https://en.wikipedia.org/wiki/Offsetof for details of container_of().
Addendum to John Bollinger's answer:
Although, IMHO, opaque pointer types with accessor functions (init/get/set/destroy) are the most secure approach, there's another option that allows users to place objects on the stack.
It's possible to allocate a single "typeless" chunk of memory as part of the struct and use that memory explicitly (bit by bit / byte by byte) instead of using additional types.
i.e.:
// public
typedef struct {
float wage;
int groupid;
/* explanation: 1 for ID and NAME_MAX_LEN + 1 bytes for name... */
unsigned long private__[1 + ((NAME_MAX_LEN + 1 + (sizeof(long) - 1)) / sizeof(long))];
} person_s;
// in .c file (private)
#define PERSON_ID(p) ((p)->private__[0])
#define PERSON_NAME(p) ((char*)((p)->private__ + 1))
This is a very strong indicator that access to the data in the private__ member should be avoided. Developers that don't have access to the implementation file won't even know what's in there.
Having said that, the best approach is an opaque type, as you may have encountered when using the pthread_t API (POSIX).
typedef struct person_s person_s;
person_s * person_new(const char * name, size_t len);
const char * person_name(const person_s * person);
float person_wage_get(const person_s * person);
void person_wage_set(person_s * person, float wage);
// ...
void person_free(person_s * person);
Notes:
avoid typedef with a pointer. It only confuses developers.
It's better to keep pointers explicit, so all developers can know that the type they're using is dynamically allocated.
EDIT: Also, by avoiding "typedefing" a pointer type, the API promises that future / alternative implementations will also use a pointer in it's API, allowing developers to trust and rely on this behavior (see comments).
When using an opaque type, the NAME_MAX_LEN could be avoided, allowing names of arbitrary length (assuming renaming requires a new object). This is an extra incentive to prefer the opaque pointer approach.
avoid placing the _ at the beginning of an identifier when possible (i.e., _name). Names starting with _ are assumed to have a special meaning and some are reserved. The same goes for types ending with _t (reserved by POSIX).
Notice how I use the _s to mark the type as a struct, I don't use _t (which is reserved).
C is more often snake_case (at least historically). The best known APIs and most of the C standard is snake_case (except where things were imported from C++).
Also, being consistent is better. Using CamelCase (or smallCamelCase) in some cases while using snake_case for other things could be confusing when developers try to memorize your API.
What John Bollinger wrote is a neat way of utilising how structs and memory works, but it's also an easy way to get a segfault (imagine allocating an array of Person and then later passing the last element to a 'method' which accesses the id or it's name), or corrupt your data (in an array of Person the next Person is overwriting 'private' variables of the previous Person). You'd have to remember that you must create an array of pointers to Person instead of array of Person (sounds pretty obvious until you decide to optimise something and think that you can allocate and initialise the struct more efficiently than the initialiser function).
Don't get me wrong, it's a great way to solve the problem, but you've got to be careful when using it.
What I'd suggest (though using 4/8 bytes more memory per Person) is to create a struct Person which has a pointer to another struct which is only defined in the .c file and holds the private data. That way it'd be harder to make a mistake somewhere (and if it's a bigger project then trust me - you'll do it sooner or later).
.h file:
#pragma once
#define NAME_MAX_LEN 20
typedef struct _person {
float wage;
int groupid;
_personPriv *const priv;
} Person;
void personInit(Person *p, const char *name);
Person* personNew(const char *name);
const char const *getName (Person *p);
int getId (Person *p);
.c file:
typedef struct {
int id;
char name[NAME_MAX_LEN];
} _personPriv;
const char const *getName (Person *p) {
return p->priv->name;
}
int getId (Person *p) {
return p->priv->id;
}
_personPriv* _personPrivNew(const char *name) {
_personPriv *ret = memcpy(
malloc(sizeof(*ret->priv)),
&(_personPriv) {
.id = generateId();
},
sizeof(*ret->priv)
);
// if(strlen(name) >= NAME_MAX_LEN) {
// raise an error or something?
// return NULL;
// }
strncpy(ret->name, name, strlen(name));
return ret;
}
void personInit(Person *p, const char *name) {
if(p == NULL)
return;
p->priv = memcpy(
malloc(sizeof(*p->priv)),
&(_personPriv) {
.id = generateId();
},
sizeof(*p->priv)
);
ret->priv = _personPrivNew(name);
if(ret->priv == NULL) {
// raise an error or something
}
}
Person* personNew(const char *name) {
Person *ret = malloc(sizeof(*ret));
ret->priv = _personPrivNew(name);
if(ret->priv == NULL) {
free(ret);
return NULL;
}
return ret;
}
Side note: this version can be implemented so that private block is allocated right after/before the 'public' part of the struct to improve locality. Just allocate sizeof(Person) + sizeof(_personPriv) and initialise one part as Person and second one as _personPriv.
Suppose I have a struct that is defined as the following:
struct entity {
int x;
int y;
};
And a struct that uses it as a member:
struct player {
struct entity position;
char* name;
};
If I write the following code then I get an error:
struct player p;
p.x = 0; //error: 'struct player' has no member named 'x'
What I have been doing so far is writing a function that takes a player struct and returns the value by doing return player.position.x.
Is there a compiler flag, or other method, that allows me to "flatten" (I'm not sure if that's the correct phrase) the struct and allows me to access the x variable like I have shown above? I realize that this might be ambiguous if there is also an integer named x inside player as well as in entity.
Please note I will be using the entity struct in multiple structs and so I cannot use a anonymous struct inside player.
Put succinctly, the answer is "No". This is especially true if you've looked at questions such as What are anonymous structs and unions useful for in C11 and found them not to be the solution.
You can look at C11 §6.7.2.1 Structure and union specifiers for more information about structure and union types in general (and ¶13 specifically for more information about anonymous members, and ¶19 for an example). I agree that they are not what you're after; they involve a newly defined type with no tag and no 'declarator list'.
Using a macro, we can make a type generator:
#define struct_entity(...) \
struct __VA_ARGS__ { \
int a; \
int b; \
}
Then we can instantiate that type as either a tagged or anonymous structure, at will:
struct_entity(entity);
struct player {
struct_entity();
const char *name;
};
int main() {
struct player player;
player.a = 1;
player.b = 2;
player.name = "bar";
}
This code is closer in intent to what you want, and doesn't have the UB problem of the approach of declaring just the structure members in the macro. Specifically, there is a structure member inside of struct player, instead of individual members. This is important, because padding reduction and reordering of members may be performed by the compiler - especially on embedded targets. E.g. composite_1 and composite_2 below do not necessarily have the same layout!:
#include <assert.h>
#include <stddef.h>
typedef struct sub_1 {
int a;
void *b;
char c;
} sub_1;
typedef struct sub_2 {
void *d;
char e;
} sub_2;
typedef struct composite_1 {
int a;
void *b;
char c;
void *d;
char e;
} composite_1;
typedef struct composite_2 {
struct sub_1 one;
struct sub_2 two;
} composite_2;
// Some of the asserts below may fail on some architectures.
// The compile-time asserts are necessary to ensure that the two layouts are
// compatible.
static_assert(sizeof(composite_1) == sizeof(composite_2), "UB");
static_assert(offsetof(composite_1, a) == offsetof(composite_2, one.a), "UB");
static_assert(offsetof(composite_1, b) == offsetof(composite_2, one.b), "UB");
static_assert(offsetof(composite_1, c) == offsetof(composite_2, one.c), "UB");
static_assert(offsetof(composite_1, d) == offsetof(composite_2, two.d), "UB");
static_assert(offsetof(composite_1, e) == offsetof(composite_2, two.e), "UB");
You can define then as MACROs:
#define ENTITY_MEMBERS int x; int y
struct entity{
ENTITY_MEMBERS;
}
struct player {
ENTITY_MEMBERS;
char* name;
};
Actually this is how you mimic C++ single inheritance in C.
i'm looking for creating a function in C language that allows me to receive different structures type as parameters.
For example, if I create 3 different structures
struct a{
struct datatype0{
char test1[10];
}datatype;
struct a *next;
};
struct b{
struct datatype1{
int test1;
char test2[20];
int test3;
}datatype;
struct b *next;
};
struct c{
struct datatype2{
char test1;
char test2;
float test3;
int test4;
int test5;
}datatype;
struct c *next;
};
I wanna create a function that can receives one of theese three different struct as parameter, so I can call only it for initialize first, or second or third kind of structure:
void function("---")//<-- inside the brackets i need to insert a parameter that can be struct a, or struct b or struct c.
{
//here for example I can insert the initialize function that have to work with any struct.
}
I tryed to use a union, but I saw that I have to recreate the initializing function for each kind of struct...I tryed to use void pointers, but i need to cast theese inside the function and I need to create initializing function for each kind of struct too...
Any ideas??
The long and short of it is: avoid to do this whenever possible, but know that you Can pass different structs to a single function if you really have to.
Probably the easiest way is to create a wrapper struct, that contains 2 members: a union, and a flag to let you know which struct is passed.
typedef enum {
A,
B,
C
} struct_type;
struct _wrapper {
union {
struct a A;
struct b B;
struct c C;
};
struct_type flag;
};
void my_function(struct _wrapper *data)
{
switch (data->flag)
{
case A:
struct a val = data.A;
//do stuff with A
break;
case B:
struct b val = data.B;
break;
case C:
struct c val = data.C;
//...
break;
}
}
Another option, although it's considered bad practice, and is something you'll end up regretting is to rely on the fact that the offset of the first member of any struct is guaranteed to be 0. You can cast a pointer to any struct to a pointer to its first member. If the first member of all structs is compatible, you can rely on that (at your own risk).
One way of exploiting this is to set a function pointer as first member, or an enum field that you can use as a flag to identify the struct:
struct a {
void (*common_member)();//
/** other members **/
};
struct b {
void (*common_member)();//needn't be the same name though
/** other members **/
};
Then:
void my_func(void *data)
{//void pointer
((void (*)(void *))data)(data);//cast void *data to function pointer, and pass itself as an argument
}
This can work, if the structs are properly initialized, and the members point to the correct functions, but that's too many if's to rely on really.
Using the enum as first member is slightly less risky, but still not to be recommended. It's a sort of a combination of the function pointer and union approach
void my_func(void *data)
{
//cast void * to struct_type *, dereference AFTER the cast
//because you can't dereference a void *
switch(*((struct_type *) data))
{
case A: /* stuff */ break;
case B: /* struct b */ break;
}
}
All in all, use the first approach. Do not use the function pointer members, and acknowledge the third approach for what it is: true, you don't need a wrapper struct, but it's not that much safer than the original approach (function pointers), and no less verbose than the first approach (with union).
Bottom line: structs and unions are the way to go
In part it works. But for example, if I wanna create a function like:
typedef union elemento{
struct a A;
struct b B;
struct c C;
}elemento;
void inserimentoOrdinato(elemento dausare){
struct b prova;
prova.datatype.test1 = 3;
strcpy(prova.datatype.test2,"TESTA");
prova.datatype.test3 = 200;
prova.next = (struct a*)malloc(sizeof(struct a));
dausare.B = prova;
}
I need to use "dausare.B" or "dausare.C" for the different kinds of structures. It doesn't know itseflt which part of union has to use. Am I rigth? Thank you!
The answer is generic programming and function pointer:
**void * can be a pointer to any struct
Declaration part:
typedef void *Initializer(void* obj);//since every struct has its own fields to initialize
void function(void * obj, Initializer init)
{
init(obj);
}
Usage:
void InitA(void* a_void)
{
struct a* a = (struct a*) a_void;
//init a feilds
a->next = NULL;
}
void InitB(void* b_void)
{
struct b* b = (struct b*) b_void;
//init b feilds
b->next = NULL;
}
void InitC(void* c_void)
{
struct c* c = (struct c*) c_void;
//init a feilds
c->next = NULL;
}
int main()
{
struct a a;
struct b b;
struct c c;
Init(&a,InitA);
Init(&b,InitB);
Init(&c, initC);
return 0;
}
***Keep in mind that you dont have to build a different function for each struct if they have the same fields to initialize.
So I have two different structs in which all the properties that I will be accessing will be the same. and I also have a function, who's argument, i want to be able to accept either of the two. Example:
typedef struct{
int whatnot = 14;
int thing[11];
} TH_CONFIG;
typedef struct{
int whatnot = 3;
int thing[5];
} TH_CONFIG_2;
*_CONFIG var;
void fun(*_CONFIG input)
{
input.whatnot = 5;
}
int main(){
fun(var);
}
I may have an inkling that I should use void as the type from that I could typecast or something?, but my searching has only yielded things about function pointers, templates, and C#.
EDIT: *_CONFIG is not meant to be syntactically correct, its signifying that I don't know what to do there, but its supposed to be the _CONFIG type
Possible solutions.
Just use an array of length 11 for both of them. Did you really run out of those last 6 bytes on your OS?
Make it a dynamic array.
Just write in assembly, you clearly don't care about C's higher-level-ness.
Use a language like C++ that supports templates or polymorphism.
Just pass in the arguments of the struct you care about.
void fun(int* whatnot) {
*whatnot = 5;
}
int main() {
fun(&myStruct.whatnot);
return 0;
}
Factor into a quasi-OO design.
struct {
int whatnot;
} typedef Common;
struct TH_CONFIG_1 {
Common common;
int thing[11];
};
struct TH_CONFIG_2 {
Common common;
int thing[5];
}
But if you insist...
void fun(void* input) {
( (int)(*input) ) = 5;
}
or...
void fun(void* input) {
( (TH_CONFIG*) input)->whatnot = 5; // may have been a TH_CONFIG_2, but who cares?
}
Note: this would not pass code review at any C shop.
You can use any pointer type and cast it.
If all the properties you're accessing are the same, I'm guessing one's an extension of the other (since the properties need to have the same offset from the beginning of the struct). In that case you may want to use this pattern:
struct base {
int foo;
char **strings;
};
struct extended {
struct base super;
double other_stuff;
};
Since super is at the start of struct extended, you can cast a struct extended * to struct base * without problems. Of course, you could do that by repeating the same fields in the beginning of struct extended instead, but then you're repeating yourself.
I've been reading about OOP in C but I never liked how you can't have private data members like you can in C++. But then it came to my mind that you could create 2 structures. One is defined in the header file and the other is defined in the source file.
// =========================================
// in somestruct.h
typedef struct {
int _public_member;
} SomeStruct;
// =========================================
// in somestruct.c
#include "somestruct.h"
typedef struct {
int _public_member;
int _private_member;
} SomeStructSource;
SomeStruct *SomeStruct_Create()
{
SomeStructSource *p = (SomeStructSource *)malloc(sizeof(SomeStructSource));
p->_private_member = 42;
return (SomeStruct *)p;
}
From here you can just cast one structure to the other.
Is this considered bad practice? Or is it done often?
sizeof(SomeStruct) != sizeof(SomeStructSource). This will cause someone to find you and murder you someday.
Personally, I'd more like this:
typedef struct {
int _public_member;
/*I know you wont listen, but don't ever touch this member.*/
int _private_member;
} SomeStructSource;
It's C after all, if people want to screw up, they should be allowed to - no need to hide stuff, except:
If what you need is to keep the ABI/API compatible, there's 2 approaches that's more common from what I've seen.
Don't give your clients access to the struct, give them an opaque handle (a void* with a pretty name), provide init/destroy and accessor functions for everything. This makes sure you can change
the structure without even recompiling the clients if you're writing a library.
provide an opaque handle as part of your struct, which you can allocate however you like. This approach is even used in C++ to provide ABI compatibility.
e.g
struct SomeStruct {
int member;
void* internals; //allocate this to your private struct
};
You almost have it, but haven't gone far enough.
In the header:
struct SomeStruct;
typedef struct SomeStruct *SomeThing;
SomeThing create_some_thing();
destroy_some_thing(SomeThing thing);
int get_public_member_some_thing(SomeThing thing);
void set_public_member_some_thing(SomeThing thing, int value);
In the .c:
struct SomeStruct {
int public_member;
int private_member;
};
SomeThing create_some_thing()
{
SomeThing thing = malloc(sizeof(*thing));
thing->public_member = 0;
thing->private_member = 0;
return thing;
}
... etc ...
The point is, here now consumers have no knowledge of the internals of SomeStruct, and you can change it with impunity, adding and removing members at will, even without consumers needing to recompile. They also can't "accidentally" munge members directly, or allocate SomeStruct on the stack. This of course can also be viewed as a disadvantage.
I do not recommend using the public struct pattern. The correct design pattern, for OOP in C, is to provide functions to access every data, never allowing public access to data. The class data should be declared at the source, in order to be private, and be referenced in a forward manner, where Create and Destroy does allocation and free of the data. In a such way the public/private dilemma won't exist any more.
/*********** header.h ***********/
typedef struct sModuleData module_t'
module_t *Module_Create();
void Module_Destroy(module_t *);
/* Only getters and Setters to access data */
void Module_SetSomething(module_t *);
void Module_GetSomething(module_t *);
/*********** source.c ***********/
struct sModuleData {
/* private data */
};
module_t *Module_Create()
{
module_t *inst = (module_t *)malloc(sizeof(struct sModuleData));
/* ... */
return inst;
}
void Module_Destroy(module_t *inst)
{
/* ... */
free(inst);
}
/* Other functions implementation */
In the other side, if you do not want to use Malloc/Free (which can be unnecessary overhead for some situations) I suggest you hide the struct in a private file. Private members will be accessible, but that on user's stake.
/*********** privateTypes.h ***********/
/* All private, non forward, datatypes goes here */
struct sModuleData {
/* private data */
};
/*********** header.h ***********/
#include "privateTypes.h"
typedef struct sModuleData module_t;
void Module_Init(module_t *);
void Module_Deinit(module_t *);
/* Only getters and Setters to access data */
void Module_SetSomething(module_t *);
void Module_GetSomething(module_t *);
/*********** source.c ***********/
void Module_Init(module_t *inst)
{
/* perform initialization on the instance */
}
void Module_Deinit(module_t *inst)
{
/* perform deinitialization on the instance */
}
/*********** main.c ***********/
int main()
{
module_t mod_instance;
module_Init(&mod_instance);
/* and so on */
}
Never do that. If your API supports anything that takes SomeStruct as a parameter (which I'm expecting it does) then they could allocate one on a stack and pass it in. You'd get major errors trying to access the private member since the one the compiler allocates for the client class doesn't contain space for it.
The classic way to hide members in a struct is to make it a void*. It's basically a handle/cookie that only your implementation files know about. Pretty much every C library does this for private data.
Something similar to the method you've proposed is indeed used sometimes (eg. see the different varities of struct sockaddr* in the BSD sockets API), but it's almost impossible to use without violating C99's strict aliasing rules.
You can, however, do it safely:
somestruct.h:
struct SomeStructPrivate; /* Opaque type */
typedef struct {
int _public_member;
struct SomeStructPrivate *private;
} SomeStruct;
somestruct.c:
#include "somestruct.h"
struct SomeStructPrivate {
int _member;
};
SomeStruct *SomeStruct_Create()
{
SomeStruct *p = malloc(sizeof *p);
p->private = malloc(sizeof *p->private);
p->private->_member = 0xWHATEVER;
return p;
}
I'd write a hidden structure, and reference it using a pointer in the public structure. For example, your .h could have:
typedef struct {
int a, b;
void *private;
} public_t;
And your .c:
typedef struct {
int c, d;
} private_t;
It obviously doesn't protect against pointer arithmetic, and adds a bit of overhead for allocation/deallocation, but I guess it's beyond the scope of the question.
There are better ways to do this, like using a void * pointer to a private structure in the public struct. The way you are doing it you're fooling the compiler.
Use the following workaround:
#include <stdio.h>
#define C_PRIVATE(T) struct T##private {
#define C_PRIVATE_END } private;
#define C_PRIV(x) ((x).private)
#define C_PRIV_REF(x) (&(x)->private)
struct T {
int a;
C_PRIVATE(T)
int x;
C_PRIVATE_END
};
int main()
{
struct T t;
struct T *tref = &t;
t.a = 1;
C_PRIV(t).x = 2;
printf("t.a = %d\nt.x = %d\n", t.a, C_PRIV(t).x);
tref->a = 3;
C_PRIV_REF(tref)->x = 4;
printf("tref->a = %d\ntref->x = %d\n", tref->a, C_PRIV_REF(tref)->x);
return 0;
}
Result is:
t.a = 1
t.x = 2
tref->a = 3
tref->x = 4
I found that bit-field might be a good solution if you really want to hide something.
struct person {
unsigned long :64;
char *name;
int age;
};
struct wallet {
char *currency;
double balance;
};
The first member of struct person is an unnamed bit-field. used for a 64-bit pointer in this case. It's completely hidden and cannot be accessed by struct variable name.
Because of the first 64-bit in this struct is unused, so we can use it as a private pointer. We can access this member by its memory address instead of variable name.
void init_person(struct person* p, struct wallet* w) {
*(unsigned long *)p = (unsigned long)w;
// now the first 64-bit of person is a pointer of wallet
}
struct wallet* get_wallet(struct person* p) {
return (struct wallet*)*(unsigned long *)p;
}
A small working example, tested on my intel mac:
//
// Created by Rieon Ke on 2020/7/6.
//
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#if __x86_64__ || __LP64__
#define PRIVATE_SET(obj, val) *(unsigned long *) obj = (unsigned long) val;
#define PRIVATE_GET(obj, type) (type)*(unsigned long *) obj;
#define PRIVATE_POINTER unsigned long:64
#else
#define PRIVATE_SET(obj, val) *(unsigned int *) obj = (unsigned int) val;
#define PRIVATE_GET(obj, type) (type)*(unsigned int *) obj;
#define PRIVATE_POINTER unsigned int:32
#endif
struct person {
PRIVATE_POINTER;
char *name;
int age;
};
struct wallet {
char *currency;
double balance;
};
int main() {
struct wallet w;
w.currency = strdup("$$");
w.balance = 99.9;
struct person p;
PRIVATE_SET(&p, &w) //set private member
p.name = strdup("JOHN");
p.age = 18;
struct wallet *pw = PRIVATE_GET(&p, struct wallet*) //get private member
assert(strcmp(pw->currency, "$$") == 0);
assert(pw->balance == 99.9);
free(w.currency);
free(p.name);
return 0;
}
This approach is valid, useful, standard C.
A slightly different approach, used by sockets API, which was defined by BSD Unix, is the style used for struct sockaddr.
My solution would be to provide only the prototype of the internal struct and then declare the definition in the .c file. Very useful to show C interface and use C++ behind.
.h :
struct internal;
struct foo {
int public_field;
struct internal *_internal;
};
.c :
struct internal {
int private_field; // could be a C++ class
};
Note: In that case, the variable have to be a pointer because the compiler is unable to know the size of the internal struct.
Not very private, given that the calling code can cast back to a (SomeStructSource *). Also, what happens when you want to add another public member? You'll have to break binary compatibility.
EDIT: I missed that it was in a .c file, but there really is nothing stopping a client from copying it out, or possibly even #includeing the .c file directly.
Related, though not exactly hiding.
Is to conditionally deprecate members.
Note that this works for GCC/Clang, but MSVC and other compilers can deprecate too,
so its possible to come up with a more portable version.
If you build with fairly strict warnings, or warnings as errors, this at least avoids accidental use.
// =========================================
// in somestruct.h
#ifdef _IS_SOMESTRUCT_C
# if defined(__GNUC__)
# define HIDE_MEMBER __attribute__((deprecated))
# else
# define HIDE_MEMBER /* no hiding! */
# endif
#else
# define HIDE_MEMBER
#endif
typedef struct {
int _public_member;
int _private_member HIDE_MEMBER;
} SomeStruct;
#undef HIDE_MEMBER
// =========================================
// in somestruct.c
#define _IS_SOMESTRUCT_C
#include "somestruct.h"
SomeStruct *SomeStruct_Create()
{
SomeStructSource *p = (SomeStructSource *)malloc(sizeof(SomeStructSource));
p->_private_member = 42;
return (SomeStruct *)p;
}
An anonymous struct can be of use here.
#ifndef MYSTRUCT_H
#define MYSTRUCT_H
typedef struct {
int i;
struct {
int j;
} MYSTRUCT_PRIVATE;
// NOTE: Avoid putting public members after private
int k;
} MyStruct;
void test_mystruct();
#endif
In any file that should have access to the private members, define MYSTRUCT_PRIVATE as an empty token before including this header. In those files, the private members are in an anonymous struct and can be accessed using m.j, but in all other places they can only be accessed using m.MYSTRUCT_PRIVATE.j.
#define MYSTRUCT_PRIVATE
#include "mystruct.h"
void test_mystruct() {
// Can access .j without MYSTRUCT_PRIVATE in both
// initializer and dot operator.
MyStruct m = { .i = 10, .j = 20, .k = 30 };
m.j = 20;
}
#include <stdio.h>
#include "mystruct.h"
int main() {
// You can declare structs and, if you jump through
// a small hoop, access private members
MyStruct m = { .i = 10, .k = 30 };
m.MYSTRUCT_PRIVATE.j = 20;
// This will not work
//MyStruct m2 = { .i = 10, .j = 20, .k = 30 };
// But this WILL work, be careful
MyStruct m3 = { 10, 20, 30 };
test_mystruct();
return 0;
}
I do not recommend putting public members after private members. Initializing a struct without member designators, such as with { 10, 20, 30 } can still initialize private members. If the number of private members changes, this will also silently break all initializers without member designators. It's probably best to always use member designators to avoid this.
You must design your structs, and especially the private members, to be zero initialized since there are no automatic constructors as in C++. As long as the members are initialized to 0 then they won't be left in an invalid state even without an initialization function. Barring a member designator initialization, initializing to simply { 0 } should be designed to be safe.
The only downside I've found is that this does mess with things like debuggers and code completion, they typically don't like it when one type has one set of members in one file, and a different set in another file.
Here's a very organized way to do it using macros. This is how I've seen it used in some of the big projects. I will assume the following:
Header file with the struct
Source file with access to private fields
Source file with no access to private fields (the fields exist but are renamed).
Header file:
// You can put this part in a header file
// and share it between multiple header files in your project
#ifndef ALLOW_PRIVATE_ACCESS
#define PRIVATE(T) private_##T
#else
#define PRIVATE(T) T
#endif
#define PUBLIC(T) T
typedef struct {
int PRIVATE(m1); // private member
int PUBLIC(m2); // public member
} mystruct;
mystruct *mystruct_create(void);
int mystruct_get_m1(mystruct *t);
Source file with access to private fields:
#include <stdlib.h>
#define ALLOW_PRIVATE_ACCESS
#include "mystruct.h"
mystruct *mystruct_create(void) {
mystruct *p = (mystruct *)malloc(sizeof(mystruct));
p->m1 = 42; // works (private)
p->m2 = 34; // works (public)
return (mystruct *)p;
}
int mystruct_get_m1(mystruct *t) {
return t->m1; // works (private)
}
Source file with no access to private fields:
#include <stdio.h>
#include <stdlib.h>
#include "mystruct.h"
int main() {
mystruct *t = mystruct_create();
printf("t->m1 = %d\n", t->m1); // error (private)
printf("t->m1 = %d\n", mystruct_get_m1(t)); // works (using function)
printf("t->m2 = %d\n", t->m2); // works (public)
free(t);
return 0;
}