Использование Tagged Unions в C для реализации математических объектов - PullRequest
0 голосов
/ 27 апреля 2020

Итак, я ухожу от этого вопроса: Более общее определение структур в C

Если бы я хотел реализовать векторы, которые могли бы содержать int или double ценности и добавить их, кто-то может помочь мне понять? Я никогда раньше не работал с enum или union.

Полагаю, это выглядит примерно так:

struct Vector
{
    size_t length;
    enum Type
    {
        INT,
        DOUBLE
    } type;
    union Data
    {
        int *int_vals;
        double *double_vals;
    } data;
};

struct Vector *create_vector(length, type) {

    struct Vector *vector = malloc(sizeof(struct Vector));
    vector->length = length;
    vector->type = type;
    vector->data = malloc(length*sizeof(type));

    return vector;
}


struct Vector *dvec1 = create_vector(2, DOUBLE);
struct Vector *dvec2 = create_vector(2, DOUBLE);
struct Vector *dvec3 = create_vector(2, DOUBLE);


dvec1->data[0] = 0
dvec1->data[1] = 1

dvec2->data[0] = 1;
dvec2->data[1] = 1;

dvec3->data[0] = dvec1->data[0] + dvec2->data[0];
dvec3->data[0] = dvec1->data[1] + dvec2->data[1];



1 Ответ

0 голосов
/ 27 апреля 2020

Я не собираюсь беспокоить вас определениями союзов, вы можете найти обширную документацию на сайте относительно предмета, например:

Зачем нам нужны C Союзы?

Назначение союзов в C и C ++

Чтобы код, который вы показываете, работал, сначала вам нужно, чтобы член data был указатель, так что вы можете выделить память для него. Затем, если вы хотите сохранить числовые значения c в его элементах, нет смысла иметь указатели be.

Вы можете присвоить структуре тип, чтобы вы могли знать, что там, но в этом случае, если вы решите всегда назначать члену большего размера, double, вы можете обойтись без него.

Вот некоторые изменения, которые я внес в ваш код, чтобы он работал, цель его не в том, обсуждается в вашем вопросе, поэтому я предполагаю, что нет, кроме понимания того, как это работает.

struct Vector
{
    size_t length;
    enum Type
    {
        INT,
        DOUBLE
    } type;
    union Data {
        int int_vals; //no pointers needed
        double double_vals;
    } * data; // pointer for memory alloctation
};

struct Vector *create_vector(int length,  enum Type type) // if you don't define a type it will default to int
{
    struct Vector *vector = malloc(sizeof(struct Vector));
    vector->length = length;
    vector->type = type;
    vector->data = malloc(length * sizeof(*vector->data)); //allocate with union size

    return vector;
}

int main(void)
{

    struct Vector *dvec1 = create_vector(2, DOUBLE);
    struct Vector *dvec2 = create_vector(2, DOUBLE);
    struct Vector *dvec3 = create_vector(2, DOUBLE);

    dvec1->data[0].int_vals = 0;
    dvec1->data[1].double_vals = 1;

    dvec2->data[0].int_vals = 1;
    dvec2->data[1].double_vals = 1;
    //assign to the larger type
    dvec3->data[0].double_vals = dvec1->data[0].int_vals + dvec2->data[0].int_vals; 
    dvec3->data[1].double_vals = dvec1->data[1].double_vals + dvec2->data[1].double_vals; //same

    printf("%.0f\n", dvec3->data[0].double_vals);
    printf("%.2f", dvec3->data[1].double_vals);

    return 0;
}

Вывод:

1
2.00
...