13

I use C and structs where a struct can have members but not functions. Assume for simplicity that I want to create a struct for strings that I name str and I want to be able to do str.replace(int i, char c) where i is the index of the string and c is the character to replace the character at position i. Would this never be possible since structs can't have functions or is there still some way we can implement this behavior and mimic that a struct could have a (simple) function that actually only is the struct copying itself to a new struct and updating its fields, which it could do?

So replace could be a third member of the struct that points to a new struct that is updated when it is accessed or similar. Could it be done? Or is there something builtin or some theory or paradigm that prevents my intention?

The background is that I'm writing C code and I find myself reinventing functions that I know are library builtins in OOP languages and that OOP would be a good way to manipulate strings and commands.

  • 5
    I honestly think you would be better off writing free functions to do this sort of thing. However, if you have the necessary moxie, read cs.rit.edu/~ats/books/ooc.pdf – Robert Harvey May 25 '16 at 3:40
  • 5
    Structs can include variables which are pointers to functions. No built in inheritance but you can instantiate your struct with the pointers pointing to different functions with the same signature. You'll often want to make the first parameter to the function a pointer to the struct. – James McLeod May 25 '16 at 3:43
  • 29
    is replace(&str, i, c) really that much worse than str.replace(i,c)? Your question isn't actually about replacing functions, it's about trying to smush a new syntax into C. – whatsisname May 25 '16 at 5:16
  • 1
    @RobertHarvey Thanks for the cs.rit.edu/~ats/books/ooc.pdf link. Nice book (and the price is right). – John Forkosh May 25 '16 at 7:46
  • 3
    @whatsisname: In C, you have to pass the structure pointer to the function anyway, so you end up with str.replace(&str, i, c) anyway. C++ automates the passing of the this pointer, of course. – Jonathan Leffler May 25 '16 at 11:30
21

Your function should look like this.

void
replace(struct string * s, int i, char c);

This accepts a pointer to the object to operate on as the first parameter. In C++, this is known as the this-pointer and need not be declared explicitly. (Contrast this to Python where it has to.)

In order to call your function, you would also pass that pointer explicitly. Basically, you trade the o.f(…) syntax for the f(&o, …) syntax. Not a big deal.

The story becomes more involved if you want to support polymorphism (aka virtual functions). It can also be emulated in C (I've shown it for this answer.) but it ain't pretty to do by hand.

As Jan Hudec has commented, you should also make it a habit to prefix the function name with the type name (ie string_replace) because C has no name-spaces so there can only be a single function named replace.

  • 17
    Of course the function will probably have to be called string_replace, because C does not have function overloading either and you are likely to have some other replace for some other type… – Jan Hudec May 25 '16 at 8:05
  • 2
    It can't be named string_replace. Names beginning with str, mem, or wcs followed by a lowercase letter are reserved for future extensions. – David Conrad May 26 '16 at 6:07
43

Structs can hold function pointers, but those are really only needed for virtual methods. Non-virtual methods in object-oriented C are usually done by passing the struct as the first argument to a regular function. Look at Gobject for a good example of an OOP framework for C. It uses macros to handle a lot of the boilerplate required for inheritance and polymorphism.

C was created 44 years ago. It's a very popular language for open source. You're not the first person to think standard C strings are clunky to work with. Do some searches for C string libraries. You don't have to reinvent the wheel.

  • 2
    Other notable example is CPython. The code uses a lot of OOP concepts yet it's 100% pure C. – Bakuriu May 25 '16 at 10:40
  • @Bakuriu I think you're confusing Cython and CPython – cat May 25 '16 at 13:13
  • 1
    @cat He probably means the Python C API, Cython isn't 100% pure C. docs.python.org/c-api/intro.html – JAB May 25 '16 at 13:39
  • 5
    @cat No. Look at CPython sources. Most of the things are indeed done using the OOP paradigm, and they provide an OOP API that mostly matches the python API. – Bakuriu May 25 '16 at 16:48
  • 1
    @Bakuriu Oh, you mean Python's runtime, source and C API not the Python language. your comment didn't make that very clear – cat May 25 '16 at 20:01
9

With function pointers, you can do:

str.replace(&str, i, c);

This is generally only useful if the implementation can change, in which case you should use a vtable so the overhead is only one pointer per struct:

str.vtable->replace(&str, i, c);
  • 3
    I'd tend to still call it as string_replace(&str, i, c) then use the vtable inside string_replace rather than have the call site know about the vtable. – Pete Kirkham May 25 '16 at 14:56
  • 2
    @Pete Names beginning with str (or mem or wcs) and a lowercase letter are reserved by the C standard for future extensions, so don't call it string_replace. str_replace is fine. – David Conrad May 26 '16 at 6:11
3

Yes, they can, sort of. You can make use of the fact that C allows for pointers to function blocks in memory, a.k.a. function pointers and using that you may create interface like polymorphism as well as virtual functions (even if it is not that pretty).

I wrote a blog post on this subject, following a question from one of my students, recently, pertaining to interface-like code in C and Go, you can read it here:

Blog post on non-OO interfaces

See if it gives you any ideas.

You could also just put a free function in your code, and use a "this"-pointer, meaning you pass a pointer to an existing struct to work on, as described in other answers.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.