views:

126

answers:

5

Given:

struct objStruct {
    int id;
    int value;
};

typedef struct objStruct Object;

Is there a shortcut to allocate and initialize the object, something 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;
+8  A: 

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);
JaredPar
It may be a bit overkill, but I usually also create a void objStruct_destroy(objStruct * obj) that does free for me, in case I need to add any freeing for allocated structs inside later.
Mike Axiak
Yes; except that it's sometimes preferable to have the "constructor" take the Object* as a parameter instead, so you can do stack allocation as well (`Object object; Object_initialise(`).
Porculus
An intermediate method would be have an Object_Init to perform initialization on an already allocated object (=placement constructor), and Object_New to allocate and init (internally it should call Object_Init). The same should be done for the "destructor".
Matteo Italia
+1  A: 

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

Tarantula
A: 
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;
}
nategoose
+2  A: 

In C99:

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.

Jonathan Leffler
+1  A: 

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++.

Jens Gustedt