Как преобразовать соглашение о параметрах GMP C в нечто более естественное?
Например, я хотел бы сделать что-то вроде этого:
#include <gmp.h>
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? Читая документацию, я предполагаю, что на самом деле это не массив, а просто ссылка, так почему же он не может вернуть ссылку? Есть ли какая-то хорошая основа звукового программирования для этого, которую я должен рассмотреть при написании своей собственной программы?
1 ответ
Из 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
здесь как "первоклассный" тип):
mpz_t number = ...;
number = DoubleIt(number);
Вы (программа) должны были бы скопировать все данные в number
и нажмите его в качестве параметра для вашей функции. Затем нужно оставить подходящее место для возврата еще большего числа.
Вывод: так как вам приходится иметь дело с данными косвенно (с указателями), лучше использовать непрозрачный тип. Вы будете передавать ссылку только на свои функции, но вы можете работать с ними так, как если бы вся концепция былапередачей по ссылке (по умолчанию C - передача по ссылке).