Магия препроцессора C для удаления избыточной ссылки на структуру данных - PullRequest
0 голосов
/ 08 октября 2018

Каждый раз в CI приходится передавать ссылку на структуру при каждом вызове функции структуры данных, например, так:

struct Array array; // array struct with int *buffer and size_t size
int size = 100;

array_init(&array, size);
array_add(array, 0, 20); // reference to array, position, value

Но очень простой способ сделать это - вызвать array_add as:

(Предположим, что внутри struct Array есть указатель add на array_add)

array->add(array, 0, 20);

Это делает код очень объектным.НО, ссылка на массив все еще там как параметр ...

Так что я подумал, что если бы можно было использовать магию препроцессора, чтобы не каждый раз передавать ссылку на массив (было бы очень полезно иметьthis ссылка тоже, если появятся какие-либо идеи).

До сих пор я дошел до этого:

#define N->display() N->_display(N) // this doesn't work :(
// would eventually do this macro for every function

typedef struct Array_s
{
    size_t size;
    int *buffer;

    int (*_insert)(struct Array_s*, size_t, int);
    int (*_display)(struct Array_s*);

} Array_t, *Array;


int _arr_init(Array *arr, size_t size);

int _arr_insert(Array arr, size_t index, int value);

int _arr_display(Array arr);


int _arr_init(Array *arr, size_t size)
{
    if (size == 0)
        return 10;

    (*arr) = malloc(sizeof(Array_t));

    if (!(*arr))
        return 5;

    (*arr)->buffer = calloc(size, sizeof(int));

    if (!(*arr)->buffer)
        return 5;

    (*arr)->size = size;

    (*arr)->_insert = _arr_insert;
    (*arr)->_display = _arr_display_raw;

    return 0;
}

int _arr_insert(Array arr, size_t index, int value)
{
    if (arr == NULL)
        return 8;

    if (index >= arr->size)
        return 1;

    if (arr->buffer[index] == 0)
    {
        arr->buffer[index] = value;

        return 0;
    }

    return 1;
}

int _arr_display(Array arr)
{
    if (arr == NULL)
        return 8;

    printf("\n[ ");

    size_t i;
    for (i = 0; i < arr->size - 1; i++)
        printf("%d, ", arr->buffer[i]);

    printf("%d ]\n", arr->buffer[arr->size - 1]);

    return 0;
}

// Delete functions and others are omitted

И в основном смогу сделать это:

int main(int argc, char const *argv[])
{
    Array arr;

    if (_arr_init(&arr, 100) == 0)
    {
        arr->display(); // doesn't work :(
    }

    return 0;
}
...