Malloc & Init - МАКРО - PullRequest
       27

Malloc & Init - МАКРО

3 голосов
/ 20 июня 2010

Можно ли переписать следующий код, чтобы он соответствовал ISO C?Следующие макросы выполняют malloc & init для данного типа и значения.

Текущий код работает с компиляторами gcc (u ses расширение gcc ), но это не стандартно.Если я использую -pedantic, я получаю предупреждения.

#ifdef __GNUC__

#define NM_CVPTR(type, value) \
    ({ \
        type * var = NULL; \
        var = nm_malloc(sizeof(*var)); \
        *var = value; \
        (const void*) var; \
    }) \

#define NM_VPTR(type, value) \
    ({ \
        type * var = NULL; \
        var = nm_malloc(sizeof(*var)); \
        *var = value; \
        (void*) var; \
    }) \

#define NM_PTR(type, value) \
    ({ \
        type * var = NULL; \
        var = nm_malloc(sizeof(*var)); \
        *var = value; \
        (type *) var; \
    }) \

#endif

Ответы [ 2 ]

3 голосов
/ 21 июня 2010

Вы можете использовать memcpy, чтобы присвоить значение и затем вернуть указатель. Далее используются две разные версии в зависимости от того, является ли ваше начальное значение примитивным типом (целое число, число с плавающей точкой, указатели ...) или оно является struct. Версия значения использует составной литерал (type){ (value) }, поэтому он действителен только в C99.

#include <stdlib.h>
#include <string.h>

static inline
void* memcpy_safe(void* target, void const* source, size_t n) {
  if (target) memcpy(target, source, n);
  return target;
}

#define NM_PTR_RVALUE(type, rvalue)                                     \
  ((type*)memcpy_safe(malloc(sizeof(type)), &(type){ (rvalue) }, sizeof(type)))

#define NM_PTR_LVALUE(type, lvalue)                                     \
  ((type*)memcpy_safe(malloc(sizeof(type)), &(lvalue), sizeof(type)))

typedef struct {
  int a;
} hoi;

hoi H7 = {.a = 7};

int main() {
  int* a = NM_PTR_RVALUE(int, 7);
  hoi* b = NM_PTR_LVALUE(hoi, H7);
}

(Добавлена ​​проверка NULL, в которой используется встроенная функция, хотя изначально она не запрашивалась.)

Кстати, в C ++, в отличие от C, оператор присваивания = возвращает lvalue, поэтому для C ++ вы, вероятно, могли бы играть в игры с этим.

3 голосов
/ 20 июня 2010

Это можно сделать с помощью оператора запятой , но в стандартном C вы не сможете объявить переменную как часть выражения, поэтому вам придется передать имя var замена на макрос:

// C - comma operator but not able to declare the storage during the
// expression.
#define NM_PTR(type, var, value) \
    (var = nm_malloc(sizeof(*var)), \
    *var = value, \
    (type * var))

В некоторых компиляторах и в C ++ вы можете объявить хранилище для var in-line следующим образом:

// C99 and C++
#define NM_PTR(type, value) \
    (type * var = nm_malloc(sizeof(*var)), \
    *var = value, \
    (type * var))

Сложность использования вышеуказанного макроса в том, что в теле макроса отсутствует область видимости блока, поэтому определение var является «видимым» на уровне блока, и каждый макрос может использоваться только один раз для каждого блока.

Редактировать: Спасибо Дженсу Гастедту за то, что он понял, что предложенный макрос C ++ не работает.

...