web-dev-qa-db-fra.com

Constructeur pour les structures en C

Donné:

struct objStruct {
    int id;
    int value;
};

typedef struct objStruct Object;

Existe-t-il un raccourci pour allouer et initialiser l'objet, quelque chose comme un constructeur C++?
Il pourrait même s'agir d'une macro de préprocesseur. Tout ce qui rend le code plus court et plus lisible:

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

En C, je crée généralement une fonction dans le style d'un constructeur qui fait cela. Par exemple (vérification d'erreur omise pour des raisons de concision)

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);
46
JaredPar

En C99 et au-delà, vous pouvez utiliser un littéral composé, qui ressemble à un cast suivi d'un initialiseur entre accolades:

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

Les deux dernières lignes produisent le même effet - l'ordre des champs n'est pas critique. Cela utilise des "initialiseurs désignés", une autre fonctionnalité C99. Vous pouvez créer un littéral composé sans utiliser les initialiseurs désignés.

26
Jonathan Leffler

En C, il est possible de déclarer une fonction en ligne avec le même nom que la 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

Il ressemble assez aux cteurs C++.

6
grekhss
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;
}
3
nategoose

Il faut vraiment distinguer l'initialisation des variables static ou auto et l'allocation dynamique sur la tête. Pour le premier, faites des initialiseurs nommés, pour le second une fonction init bien spécifiée.

Tout cela peut être bien emballé dans des macros ne vous donne un _ static/auto initialisation et quelque chose de similaire à new en C++.

2
Jens Gustedt

Si vous recherchez une "émulation" orientée objet sur C, je recommande fortement le système de type GObject [1], il est mature et largement utilisé par GTK par exemple.

GLib [2] a également un allocateur de tranche Nice pour les petits objets, actuellement utilisé par GNOME.

[1] Manuel de référence GObject

[2] tranches de mémoire GLib

1
Tarantula