C 存储mpz_t的地址并传递指针
据我所知,C 存储mpz_t的地址并传递指针,c,pointers,scope,gmp,nan-boxing,C,Pointers,Scope,Gmp,Nan Boxing,据我所知,mpz\u t只不过是一个单项目数组 根据: 这意味着,给定C处理数组的方式,mpz_t本身实际上就是一个指针(指向单元素数组的第一个元素) 现在,假设我在一个函数中创建一个新的mpz\u t,将指针“box”在一个无符号的long中并返回,然后。。。混乱。(因为,我猜,指针不再有效?) 理论上,我能使它工作的唯一方法是将mpz\u t声明移到函数体之外(基本上,使其成为全局的) 还有其他更明智的想法吗 最小示例: typedef uint64_t Value; #define a
mpz\u t
只不过是一个单项目数组
根据:
这意味着,给定C处理数组的方式,mpz_t本身实际上就是一个指针(指向单元素数组的第一个元素)
现在,假设我在一个函数中创建一个新的mpz\u t
,将指针“box”在一个无符号的long中并返回,然后。。。混乱。(因为,我猜,指针不再有效?)
理论上,我能使它工作的唯一方法是将mpz\u t
声明移到函数体之外(基本上,使其成为全局的)
还有其他更明智的想法吗
最小示例:
typedef uint64_t Value;
#define addWillOverflow(x,y,z) __builtin_sadd_overflow(x,y,z)
#define BITFIELD 56
#define MASK(x) ((Value)(x) << BITFIELD)
#define UNMASK 0x00FFFFFFFFFFFFFF
#define toI(v) ( (Value)(v & 0xFFFFFFFFu) | MASK(IV) )
#define toG(v) ( (Value)(v) | MASK(GV) )
#define GG(v) ( (v & UNMASK) )
Value addNumbers(int a, int b) {
Int32 res;
if (addWillOverflow(a,b,&res)) {
printf("overflow\n");
mpz_t ret;
mpz_init_set_si(ret,a);
mpz_add_ui(ret,ret,b);
return toG(ret);
}
else {
printf("normal addition\n");
return toI(res);
}
}
int main(int argc, char** argv) {
printf("3 + 5 = ");
printLnValue(addNumbers(1,2));
printf("2b + 2b = ");
Value a = addNumbers(2000000000,2000000000);
printLnValue(a);
printf("pointer: %p\n",GG(a));
Value b = addNumbers(2100000000,2011111111);
printLnValue(b);
printf("pointer: %p\n",GG(b));
}
3 + 5 = normal addition
3
2b + 2b = overflow
4000000000
pointer: 0x7ffee5b95630
overflow
4111111111
pointer: 0x7ffee5b95630
如您所见,返回的指针是。。。相同的。虽然我期待一个不同的
第2次更新 我目前正在考虑这样做:(我会看看它是如何运行的,然后自己把它作为一个解决方案发布)
向我们展示您的实际代码。@JohnZwinck我将尝试制作一个最小的示例。@JohnZwinck我刚刚在其输出中添加了一些示例代码,以了解我的问题所在。为什么您希望使用不同的地址
ret
显然是一个局部变量(即堆栈分配)。无论如何,malloc
解决方案是正确的。您可能会对中的注释感兴趣。您的目标是返回一个mpz_t,只需看看GMP是如何实现的(例如mpz_添加)。或者移动到C++,使用MPZL类,就像你使用int一样,并且担心其他的东西。
3 + 5 = normal addition
3
2b + 2b = overflow
4000000000
pointer: 0x7ffee5b95630
overflow
4111111111
pointer: 0x7ffee5b95630
mpz_t* ret = malloc(sizeof(mpz_t));
mpz_init_set_si(*ret,a);
mpz_add_ui(*ret,*ret,b);
return toG(ret);