1

I've use quite a bit of JavaScript so far. If you were to use an object constructor in JavaScript, you have access to the this constructor.

So my question relates to trying to use a similar concept in C. I created a struct that I want to be able to self reference:

struct Storage {
    void (*delete)();
}

So if I were to allocate a Storage class:

struct Storage *myStruct = malloc(sizeof(struct Storage));

Let's say I'm trying to delete myStruct. If I have some delete function that I point to (with myStruct->delete = deleteStructure), I would like to do something like this:

myStruct.delete();

which would then free() the struct through a self referencing variable inside of said delete function. I'm wondering if there would be a way to have the delete function look like:

void deleteStructure() {
    free( /* "this" or some equivalent C self-reference */ );
}

My assumption from research so far is that this is not possible since this is usually only in object oriented programming languages. If this is not possible, I'm wondering what would be the semantically correct way to do this. I'm hoping to make the usage of this delete functionality rather simplistic from a user interface perspective. The only way I understand this to work would be passing a reference to the structure like:

void deleteStructure(struct Storage *someStructure) {
    free(someStructure);
}

which would then require deletion to be done as follows:

deleteStructure(myStruct);

To sum up: is there a way to make a delete function that uses self references in C, and if not, what would be the most semantically correct way to delete a structure in the most user friendly way?

Robert Columbia
  • 6,313
  • 15
  • 32
  • 40
charlie-map
  • 556
  • 5
  • 17
  • 3
    No. C does not have classes. For that we have C++. So no functions in struct and no "this". – Heto Dec 17 '21 at 22:58
  • 3
    C does not pass any implicit arguments to functions, if you want to have a `this` then it needs to be passed in explicitly – UnholySheep Dec 17 '21 at 22:59
  • @charlie-map why you've choose C to solve this? – Heto Dec 17 '21 at 23:00
  • @Heto You can definitely have functions in structs by utilizing function [pointers](https://stackoverflow.com/questions/9871119/define-functions-in-structs). I doubted there would be a "this", however I wonder the best way of writing something that is UI friendly with explicit pass-in. – charlie-map Dec 17 '21 at 23:01
  • What do you mean by "UI friendly"? – UnholySheep Dec 17 '21 at 23:05
  • I'm in the process of creating a database implementation in C, so I'm hoping to make everything accessible through the singular structure. So if you try to query the data you could something like `myStruct.query("SELECT etc...");` I was curious if there might be a way to make destroying the structure simple from a user perspective. @UnholySheep see my comment on mrks's answer which is my current assumption of the way I could do this. – charlie-map Dec 17 '21 at 23:09
  • @charlie-map: I think you've got this wrong :). You must fill that function pointer with something before calling it, and you can put any function that meets the "signature". Is not near the same thing :). – Heto Dec 17 '21 at 23:10
  • That sounds like you are over-complicating things. Any common C library will expose functions in the form of `functionname(objecttype *object, /* remaining arguments */)` - this is what C programmers are used to. – UnholySheep Dec 17 '21 at 23:11
  • @UnholySheep Makes sense! If you could add an answer, I can accept. – charlie-map Dec 17 '21 at 23:15
  • You are looking for a closure that can be transformed into a function pointer. It cannot be done reliably in a pure c. Neither in c++. But it can done with a help of a library i.e. callback. See https://www.gnu.org/software/libffcall/callback.html – tstanisl Dec 17 '21 at 23:51

2 Answers2

4

No. You cannot even define a function for a struct.

struct Storage {
    void (*delete)();
}

simply stores a pointer to a void function. That could be any void function and when it is being called, it has no connection to Storage whatsoever.

Also note that in your code, every instance of the struct stores one pointer to a void function. You could initialize them so that they all point to the same function, in which case you would simply waste 64 bit per instance without any real benefit. You could also make them point to completely different functions with different semantics.

mrks
  • 8,033
  • 1
  • 33
  • 62
  • Correct - I'm not trying to define a function inside of the struct. I was wondering if there was a way to delete a struct through a function that is attached inside of said struct (using a pointer). I'm assuming I would have to do `myStruct.delete(myStruct);`, but I was hoping for something a bit more friendly in terms of simplicity for use. – charlie-map Dec 17 '21 at 23:05
  • 2
    But you can store function pointers in a C `struct` and can also emulate `this` keyword with another pointer. – Super-intelligent Shade Dec 17 '21 at 23:07
  • 1
    Oh interesting @InnocentBystander. Could I theoretically store a pointer to the struct inside of the struct itself? I'm still not sure I could access that struct pointer in a function that I'm pointing to – charlie-map Dec 17 '21 at 23:12
  • 2
    @charlie-map: don't do this, use the right tool in the right way. You want OOP, do it in C++. You want it in C, do it in C way(procedural). – Heto Dec 17 '21 at 23:13
  • @charlie - If you store a pointer in the struct, you will soon copy the struct and then the pointer points to the wrong struct... – BoP Dec 18 '21 at 10:31
1

As per @UnholySheep's comment, the correct semantical use of a struct with connection to a C function will follow the structure:

struct Storage {
    /* Some definitions here */
}

void deleteStructure(struct Storage *someStructure) {
    free( /* all inner structure allocations */ );

    free(someStructure);
}

Here's more about passing structs by reference.

charlie-map
  • 556
  • 5
  • 17