0

我正在尝试实现一个 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(使用、分配、符号等),然后知道偏移量后访问 mp_digit[],但我不喜欢这个想法。我想知道哪种方法更好。

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

谢谢,

4

2 回答 2

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 字节数组不兼容,例如此处

于 2017-07-30T08:37:51.180 回答
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;
}
于 2017-07-30T08:16:58.147 回答