Конструктор для структур в Си - PullRequest
37 голосов
/ 23 сентября 2010

Дано:

struct objStruct {
    int id;
    int value;
};

typedef struct objStruct Object;

Есть ли ярлык для выделения и инициализации объекта, что-то вроде конструктора C ++?
Это может быть даже макрос препроцессора. Все, что делает код короче и более читабельным, чем это:

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

Ответы [ 6 ]

45 голосов
/ 23 сентября 2010

В CI обычно создают функцию в стиле конструктора, которая делает это.Например (проверка ошибок для краткости опущена)

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);
24 голосов
/ 23 сентября 2010

В 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 };

Последние две строки достигают одинакового эффекта - порядок полей не является критическим. Это использует «назначенные инициализаторы», еще одну особенность C99. Вы можете создать составной литерал без использования назначенных инициализаторов.

6 голосов
/ 27 мая 2015

В C можно объявить встроенную функцию с тем же именем, что и структура:

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

Это выглядит очень похоже на C ++ ctors.

3 голосов
/ 23 сентября 2010
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;
}
2 голосов
/ 23 сентября 2010

Вы действительно должны различать инициализацию static или auto переменных и динамическое распределение по голове. Для первого сделайте именованные инициализаторы, для второго - хорошо определенную функцию init.

Все это может быть красиво упакованный в макросы дает вам легкую инициализацию static/auto и что-то похожее на new в C ++.

1 голос
/ 23 сентября 2010

Если вы ищете объектно-ориентированную «эмуляцию» над C, я настоятельно рекомендую систему типов GObject [1], она является зрелой и широко используется, например, GTK.

GLib [2] также имеетхороший распределитель слайсов для небольших объектов, в настоящее время используемый GNOME.

[1] Справочное руководство GObject

[2] GLib Memory Slices

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...