Подтвердить что ты не робот

Конструктор для структур в C

Дано:

struct objStruct {
    int id;
    int value;
};

typedef struct objStruct Object;

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

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

Ответ 1

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

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

Ответ 2

В 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. Вы можете создать составной литерал без использования назначенных инициализаторов.

Ответ 3

В 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

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

Ответ 4

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

Ответ 5

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

Все, что может быть красиво упакованные в макросы дают вам легкую static/auto intialization и что-то похожее на new в С++.

Ответ 6

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

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

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

[2] Метки памяти GLib