我正在尝试实现一个bigInt库。我一直在检查其他库,如GMP,ttmaht或libtommath,但其中任何一个都满足项目的要求(因为许可证,因为它们只使用堆栈等)
我将遵循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 one或this one,但它们并没有全部存储在堆中,所以我的有点棘手/不同。
谢谢,
答案 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;
}