HiveBrain v1.2.0
Get Started
← Back to all entries
snippetcMinor

Example String Class in C

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
exampleclassstring

Problem

I wrote this small example piece of OOP being implemented in pure C. I wanted it to be reviewed for the following points:

  • Portability



-
Performance

And especially

  • Usability



  • "How does it look"



Implementation:

typedef char    XCFString;

struct XCFStringStatic {
    void *(*initWithCString)(const char *);
};

struct XCFStringClass {
    void (*release)(void);

    size_t      length;
    char        *value;
};

// Pointer to current class
XCFString **XCFStringCTX    = NULL;

// Release method
void XCFString__release(void)
{
    assert(XCFStringCTX != NULL);
    XCFString *ctx  = *XCFStringCTX;

    free(((char *)ctx) - sizeof(struct XCFStringClass));
}

// Init method
void *XCFString__initWithCString(const char *str)
{
    size_t str_len              = strlen(str);
    struct XCFStringClass *data = malloc(sizeof(* data) + str_len + 1);

    if (!data) return NULL;

    char *str_val               = ((char *)data) + sizeof(* data);

    memcpy(str_val, str, str_len + 1);

    data->length                = str_len;
    data->value                 = str_val;
    data->release               = XCFString__release;

    return data->value;
}

struct XCFStringStatic XCFStringStatic = {.initWithCString = XCFString__initWithCString};

#define priv_getMacroName1(_0, _1, macroName, ...)          macroName
#define getMacroName1(macroName, args...)                   priv_getMacroName1(_0, ##args, macroName ## _1, macroName ## _0)(args)

#define XCFString_0()       (XCFStringStatic)
#define XCFString_1(_var)   (XCFStringCTX=&(_var), ((struct XCFStringClass *)(((char *)_var) - sizeof(struct XCFStringClass))))
// Switch between XCFString_0 and XCFString_1, GNUC only
#define XCFString(args...)                                  getMacroName1(XCFString, ##args)


Test code for main.c

```
int main(int argc, const char **argv)
{
// Pointer to our String class
XCFString *string = NULL;

// Initialize string with "Hallo Welt!"
string = XCFString(

Solution

I would actually avoid the attempt to mimic C++ syntax. It makes things more complex and exposes unnecessary details.

For me it would be equally object-oriented with the following C interface:

#ifdef __cplusplus
#extern "C" {
#endif

typedef struct XCFString_
{
    char unused__;
} XCFString;

XCFString* XCFString_Init();
XCFString* XCFString_InitFromCString(char const* sz);
size_t XCFString_Length(XCFString const* xcfs);
char const* XCFString_Value(XCFString const* xcfs);
void XCFString_Release(XCFString* xcfs);

#ifdef __cplusplus
}
#endif


The above interface hides the details while allowing polymorphism; you could e.g. keep the "vtable" implementation (but hidden) and provide different init-functions.

I really don't follow all that macro voodoo but having a mutable shared state - the "pointer to current class" - seems susceptible to race conditions.

Code Snippets

#ifdef __cplusplus
#extern "C" {
#endif

typedef struct XCFString_
{
    char unused__;
} XCFString;

XCFString* XCFString_Init();
XCFString* XCFString_InitFromCString(char const* sz);
size_t XCFString_Length(XCFString const* xcfs);
char const* XCFString_Value(XCFString const* xcfs);
void XCFString_Release(XCFString* xcfs);

#ifdef __cplusplus
}
#endif

Context

StackExchange Code Review Q#66906, answer score: 2

Revisions (0)

No revisions yet.