在堆中定义具有不同大小的结构

时间:2017-07-30 07:53:38

标签: c++ c heap-memory biginteger multiprecision

我正在尝试实现一个bigInt库。我一直在检查其他库,如GMPttmahtlibtommath,但其中任何一个都满足项目的要求(因为许可证,因为它们只使用堆栈等)

我将遵循libtommath的方法(非常好地记录并在C中编写)但我希望所有存储在堆中。 libtommath在类似这样的结构中实现了bigInt:

typedef struct  {
    int used, alloc, sign;
    mp_digit *dp;
} mp_int;

正如您所看到的,它具有访问值的间接性。 (mp_digit是大整数的数字)。我想摆脱间接,所以在堆中有一些类似的结构,其中最后一个元素是mp_digit [],其中每个mp_int实例的大小可以不同。

我可以使用void *和malloc()知道前X个位置是int的信息(used,alloc,sign等),然后访问知道偏移的mp_digit []但我不喜欢这个理念。我想知道哪种方法更好。

我发现了其他类似的问题,例如this onethis one,但它们并没有全部存储在堆中,所以我的有点棘手/不同。

谢谢,

2 个答案:

答案 0 :(得分:2)

C 中,mp_digit dp[]表示灵活数组成员。这出现在C99:

typedef struct  {
    int used, alloc;
    signed char sign;
    mp_digit dp[];
} mp_int;

您可以使用malloc(sizeof(mp_int) + alloc * sizeof(mp_digit));分配内存;还有realloc。

然而,根据mp_digit的类型,有一个不起眼的东西可能会帮助您保存一两个字节 - 即dp的偏移量不一定是sizeof(mp_int)但是可能会少一些;有一个kludgey宏hack用于计算要分配的实际最小大小(但这仍然是可移植的)。

该定义在C ++中不起作用,但您可以在C ++中使用指向不完整类型的指针。

请注意,灵活的数组成员不兼容<1>字节数组,例如here

答案 1 :(得分:0)

在C中像这样创建

mp_int *LN_Create(int ndigits, int allocate)
{
    mp_int *ln = calloc(1, sizeof mp_int);

    if (ln != NULL)
    {
        ln->ndigits = ndigits;
        if (allocate)
        {
            ln->dp = calloc(ndigits, sizeof mp_digit);
            ln->alloc = 1;
            if (ln->dp == NULL)
            {
                free(ln);
                ln = NULL;
            }
        }
    }
    return ln;
}

mp_int *LN_Create1(int ndigits)
{
    size_t allocsize = sizeof mp_int + (ndigits - 1) * sizeof mp_digit;
    mp_int *ln = malloc(allocsize);

    if (ln != NULL)
    {
        memset(ln, 0, allocsize);
        ln->ndigits = ndigits;
    }
    return ln;
}