In common C, one would not expect a to be modified by foo() as C is pass by value . Yet since a is an array of __mpz_struct, a is converted from its value as an array to the addresses of a[0]. It is that address that is passed by value to foo. Now foo() can change the caller's a.
This should use const to indicate which may change.
void dec_alt1(mpz_t* m, const mpz_t* c, const mpz_t* d, const mpz_t* n) {
mpz_powm(*m, *c, *d, *n);
}
It is quite unnecessary to pass 4 mpz_t* as that is 4 pointers to pointers. Code could have been the following which is also passing 4 pointers.
void dec_alt1dec_alt2(mpz_t m, const mpz_t c, const mpz_t d, const mpz_t n) {
mpz_powm(m, c, d, n);
}
void dec_alt2dec_alt3(mpz_t *m, const mpz_t c, const mpz_t d, const mpz_t n) {
mpz_powm(*m, c, d, n);
}