Is there a C macro for member methods?

Functions can be associated with their reference structure using function pointers.

struct string
{
    char *value;
    size_t (*size)(struct string *);
};

size_t size(struct string *this)
{
    size_t i;
for(i = 0; this->value[i] != '\0'; ++i);
return i;
}

struct string *construct()
{
    string this = (string)malloc(sizeof(struct string));
    this.size = &size;
    // ...
}

int main()
{
    struct string *s = construct();
    // ...
    s->size(s); // explicitly pass self reference
}

But I would like to get rid of passing the pointer thismanually. I know this is done implicitly in C ++ when you call an object method. Is there a way to create a macro for this in C that works for all methods and signatures?

For example, I could introduce syntax like this.

s=>size(); // implicitly pass self reference

Please note that this is for educational purposes only. I know it is better to use C ++ if possible, and you want to use class concatenation. But I wonder how this can be done in C.

+4
source share
2 answers

, , :

// ...

#define CALL_METHOD(x, y, ...) x->y(x, ##__VA_ARGS__)

struct string
{
    char *value;
    size_t (*size)(struct string *);
    int (*compare)(struct string *, struct string *);
    int (*set_value)(struct string *, const char *);
};

// ...

int main()
{
    // ...

    CALL_METHOD(s1, set_value, "foo");
    CALL_METHOD(s2, set_value, "bar");

    printf("s1->size(s1) = %zu;\n", s1->size(s1));
    printf("CALL_METHOD(s1, size) = %zu;\n", CALL_METHOD(s1, size));
    printf("s1->compare(s1, s2) = %d;\n", s1->compare(s1, s2));
    printf("CALL_METHOD(s1, compare, s2) = %d;\n", CALL_METHOD(s1, compare, s2));

    // ...
}
+3

s- > size().

, .

GCC

#include <stdio.h>
#include <stdlib.h>

typedef struct {
        const char *value;
        size_t (*size)();
        void (*destroy)();
} string;

#define STRING(A)                                               \
        string *A = (string *) malloc(sizeof(string));          \
        A->value = "";                                          \
        {                                                       \
                size_t size() {                                 \
                        size_t i;                               \
                                                                \
                        for(i = 0; A->value[i] != '\0'; ++i);   \
                        return i;                               \
                }                                               \
                                                                \
                void destroy() {                                \
                        free(A);                                \
                }                                               \
                                                                \
                A->size = &size;                                \
                A->destroy = &destroy;                          \
        }

int main() {
        printf("\n=== s1 ===\n");
        STRING(s1);
        printf("Size: %ld\n", s1->size());
        s1->value = "FOOO";
        printf("%s\n", s1->value);
        printf("Size: %ld\n", s1->size());

        printf("\n=== s2 ===\n");
        STRING(s2);
        printf("Size: %ld\n", s2->size());
        s2->value = "BAZ";
        printf("%s\n", s2->value);
        printf("Size: %ld\n", s2->size());

        printf("\n=== s1 ===\n");
        s1->value="A";
        printf("Size: %ld\n", s1->size());
        printf("%s\n", s1->value);

        printf("\n=== s2 ===\n");
        s2->value="ZZ";
        printf("Size: %ld\n", s2->size());
        printf("%s\n", s2->value);

        s1->destroy();
        s2->destroy();

        return 0;
}

C

#include <stdio.h>
#include <stdlib.h>

#define STRING(A)                                               \
        string *A = (string *) malloc(sizeof(string));          \
        A->value = "";                                          \
        A->size = &size;                                        \
        A->destroy = &destroy;

#define USE(A)                                                  \
        s = A;

typedef struct {
        const char *value;
        size_t (*size)();
        void (*destroy)();
} string;

size_t size();
void destroy();

string *s;

size_t size() {
        size_t i;

        for(i = 0; s->value[i] != '\0'; ++i);
        return i;
}

void destroy() {
        free(s);
}

int main() {
        printf("\n=== s1 ===\n");
        STRING(s1);
        USE(s1);
        printf("Size: %ld\n", s1->size());
        s1->value = "FOOO";
        printf("%s\n", s1->value);
        printf("Size: %ld\n", s1->size());

        printf("\n=== s2 ===\n");
        STRING(s2);
        USE(s2);
        printf("Size: %ld\n", s2->size());
        s2->value = "BAZ";
        printf("%s\n", s2->value);
        printf("Size: %ld\n", s2->size());

        USE(s1);
        printf("\n=== s1 ===\n");
        s1->value="A";
        printf("Size: %ld\n", s1->size());
        printf("%s\n", s1->value);

        USE(s2);
        printf("\n=== s2 ===\n");
        s2->value="ZZ";
        printf("Size: %ld\n", s2->size());
        printf("%s\n", s2->value);

        USE(s1);
        s1->destroy();

        USE(s2);
        s2->destroy();

        return 0;
}
+1

Source: https://habr.com/ru/post/1524780/


All Articles