开发者

Constructor for structs in C

开发者 https://www.devze.com 2023-01-17 01:06 出处:网络
Given: struct objStruct { int id; int value; }; typedef struct objStruct Object; Is there a shortcut to allocate and initialize the object, someth开发者_JS百科ing like a C++ constructor?

Given:

struct objStruct {
    int id;
    int value;
};

typedef struct objStruct Object;

Is there a shortcut to allocate and initialize the object, someth开发者_JS百科ing like a C++ constructor?

It could even be a preprocessor macro. Whatever makes the code shorter and more readable than this:

Object *newObj = malloc(sizeof(Object));
// successful allocation test snipped
newObj->id = id++;
newObj->value = myValue;


In C I typically create a function in the style of a constructor which does this. For example (error checking omitted for brevity)

Object* Object_new(int id, int value) { 
  Object* p = malloc(sizeof(Object));
  p->id = id;
  p->value = value;
  return p;
}

...
Object* p1 = Object_new(id++, myValue);


In C99 and beyond, you can use a compound literal, which looks like a cast followed by an initializer in braces:

int init_value = ...;
int init_id    = ...;
Object newObj1 = (Object){ .value = init_value, .id = init_id };
Object newObj2 = (Object){ .id = init_id, .value = init_value };

The latter two lines achieve the same effect - the order of the fields is not critical. That is using 'designated initializers', another C99 feature. You can create a compound literal without using designated initializers.


In C it is possible to declare an inline function with the same name as structure:

struct my
{
    int a;
};

inline struct my* my(int* a)
{
    return (struct my*)(a);
}

//somewhere in code
int num = 123;
struct my *sample = my(&num);
//somewhere in code

It looks pretty similar to C++ ctors.


struct thingy {
   char * label;
   int x;
};

#define declare_thingy( name, label, val) struct thingy name = { label, val }

struct thingy * new_thingy(const char * label, int val) {
     struct thingy * p = malloc(sizeof(struct thingy));
     if (p) {
          p->label = label;
          p->val = val;
     }
     return p;
}


You really have to distinguish initialization of static or auto variables and dynamic allocation on the head. For the first, do named initializers, for the second a well specified init function.

All that can be nicely packed into macros do give you an easy static/auto intialization and something similar to new in C++.


If you are looking for an object oriented "emulation" over C, I strongly recommend the GObject Type System [1], it's mature and largely used by GTK for instance.

GLib [2] has also a nice slice allocator for small objects, currently used by GNOME.

[1] GObject Reference Manual

[2] GLib Memory Slices

0

精彩评论

暂无评论...
验证码 换一张
取 消