Как преобразовать соглашение о параметрах GMP C в нечто более естественное?

Например, я хотел бы сделать что-то вроде этого:

#include  typedef mpz_t Integer; // Integer F(Integer a,Integer b,Integer c,Integer d) { Integer ret = times(plus(a,b),plus(c,d)); } 

Но GMP не позволяет мне это делать, очевидно, mpz_t – это массив, поэтому я получаю ошибку:

 error: 'F' declared as function returning an array 

Поэтому вместо этого я должен был бы сделать что-то вроде этого:

 void F(Integer ret,Integer a,Integer b,Integer c,Integer d) { Integer tmp1,tmp2; plus(tmp1,a,b); plus(tmp2,c,d); times(ret,tmp1,tmp2); } 

Это неестественно и не следует логическому способу сложения C (или вообще математических) выражений. Фактически, вы не можете составить что-либо математически, потому что, по-видимому, вы не можете вернуть номера GMP! Если бы я хотел написать – например, простой синтаксический анализатор yacc / bison, который преобразовал простой синтаксис с помощью +, -, /, * и т. Д. В код C, реализующий данные выражения с использованием GMP, кажется, было бы намного сложнее, так как я необходимо будет отслеживать все промежуточные значения.

Итак, как я могу заставить GMP согнуть мою волю здесь и принять более разумный синтаксис? Могу ли я безопасно «обмануть» и бросить mpz_t в пустоту *, а затем восстановить его на другом конце обратно в mpz_t? Я берусь от чтения документации, что она действительно не проходит вокруг массива, а просто ссылку, поэтому почему она не может вернуть ссылку? Есть ли какая-то хорошая основа для звукового программирования для этого так, что я должен рассмотреть при написании моей собственной программы?

Из gmp.h :

 typedef __mpz_struct mpz_t[1]; 

Это имеет большой смысл, и это довольно естественно . Подумайте об этом: наличие массива размером 1 позволяет вам иметь дело с скрытым указателем (известным как непрозрачная ссылка) и всеми его преимуществами:

 mpz_t number; DoubleIt(number); /* DoubleIt() operates on `number' (modifies it) as it will be passed as a pointer to the real data */ 

Если бы это не массив, вам нужно было бы сделать что-то вроде:

 mpz_t number; DoubleIt(&number); 

И тогда наступает вся путаница. Намерение за непрозрачным типом состоит в том, чтобы скрыть их, поэтому вам не нужно беспокоиться об этом. И одна из основных проблем должна быть ясной: размер (что приводит к производительности). Конечно, вы не можете вернуть такую ​​структуру, которая хранит данные, ограниченные доступной памятью. Как насчет этого (рассмотрите mpz_t здесь как «первоclassный» тип):

 mpz_t number = ...; number = DoubleIt(number); 

Вы (программа) должны будут скопировать все данные в number и направить его в качестве параметра вашей функции. Затем ему нужно оставить подходящее пространство для возвращения еще большего числа.

Вывод: поскольку вам приходится иметь дело с данными косвенно (с указателями), лучше использовать непрозрачный тип. Вы передадите ссылку только на свои функции, но вы можете работать с ними, как будто вся концепция была передачей по ссылке (по умолчанию используется по умолчанию).