snippetcMinor
Example String Class in C
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:
-
Performance
And especially
Implementation:
Test code for
```
int main(int argc, const char **argv)
{
// Pointer to our String class
XCFString *string = NULL;
// Initialize string with "Hallo Welt!"
string = XCFString(
- 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:
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.
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
}
#endifThe 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
}
#endifContext
StackExchange Code Review Q#66906, answer score: 2
Revisions (0)
No revisions yet.