3

Background

I'm using the C interface to the GMP library and I have a need to manipulate arrays of integers. Main type for integers in the GMP library is mpz_t, and GMP is using a trick to allow the users to use gmp_z without explicit allocation, while being able to pass them around as pointers. Namely the gmp_z type is defined as follows.

typedef struct
{
  int _mp_alloc;        
  int _mp_size;
  mp_limb_t *_mp_d;
} __mpz_struct;

typedef __mpz_struct mpz_t[1];

This is neat, but I am having trouble passing arrays of mpz_t to functions that operate on const arrays.

Example

To exemplify consider this simple non-GMP program.

#include <stdio.h>

typedef struct {
  int x;
} x_struct;

typedef x_struct x_t[1];

void init_x(x_t x) {
  x->x = 23;
}

void print_x(const x_t x) {
  printf("x = %d\n", x->x);
}

// I'm just printing so taking a const array 
void print_x_array(const x_t* x_array, size_t n) {
  size_t i;
  for (i = 0; i < n; ++ i) {
    printf("x[%zu] = %d\n", i, x_array[i]->x);
  } 
}

int main() {
  x_t x; // I can declare x and it's allocated on the stack
  init_x(x);
  print_x(x); // Since x is an array, pointer is passed

  x_t x_array[3];
  init_x(x_array[0]);
  init_x(x_array[1]);
  init_x(x_array[2]);
  print_x_array(x_array, 3); // Compile warning
}

The program uses the GMP trick, just showing off the usage. Compiling this program gives an annoying warning

gcc test.c -o test
test.c: In function ‘main’:
test.c:33:3: warning: passing argument 1 of ‘print_x_array’ from incompatible pointer type [enabled by default]
test.c:17:6: note: expected ‘const struct x_struct (*)[1]’ but argument is of type ‘struct x_struct (*)[1]’

Question

Since I'm not a C expert, can someone please shed more light on why this warning is happening at all. More importantly, is there a way to get around this warning while still using mpz_t (or x_t in the example)?

Dejan Jovanović
  • 2,085
  • 1
  • 16
  • 22

2 Answers2

0

Just cast it to const:

  print_x_array((const x_t *)x_array, 3); // Should be ok
Michael Pankov
  • 3,581
  • 2
  • 23
  • 31
  • Although this works it is not a completely satisfactory solution. I'm providing many such functions, and the developers/users of the functions would need to cast the arrays every time they use it. – Dejan Jovanović Oct 31 '13 at 03:38
  • @DejanJovanović then either declare your array to be `const` either function argument to be non-`const`. – Michael Pankov Oct 31 '13 at 08:59
  • Moreover — it's a warning, you can ignore it and/or disable it. – Michael Pankov Oct 31 '13 at 09:00
  • Ignoring the incompatible pointer warning for a large project is bad practice. – Dejan Jovanović Oct 31 '13 at 18:27
  • @DejanJovanović I suggested you two more ways of fixing it. – Michael Pankov Oct 31 '13 at 18:32
  • the other two are also not appealing. as an interface the print function provides const "guarantee" so removing the const is bad. requiring only const objects is even less attractive. i'm not looking for a hack to make this particular program compile with no warnings, i'm looking for a general scalable way of dealing with it. – Dejan Jovanović Oct 31 '13 at 23:14
  • Constness in C is pretty much strapped-on. The only viable option in my opinion is actually requiring `const` annotation for function arguments. There are no other ways apart from which I've listed. – Michael Pankov Nov 01 '13 at 08:45
0

First, let's note that the compiler warning you are getting has absolutely nothing to do with GMP, their strategy of typedefing a mpz_t type as an array of size one so that it facilitates some function calls within the library (but only facilitates scalar argument passing), nor to the passing of arrays to functions, and nor its a real problem in itself actually.

The problem all relies on the const declaration of function parameter input, and that is not a true issue. Its good to have that definition, so compiler will balk if function writer attempts to modify the object being passed to the function. But burden cannot be put on function callers!

In my setting (OpenSUSE, x86_64, gcc version 9.2.1) your code does not gives a warning and works perfectly fine if I don't use the -pedantic compiler option. This is because, as Michael Pankov stated, the (old) C standard is pretty tight and sometimes cumbersome, while compilers today are very smart. The compiler does now what you want, and will provide you correct code, be assured of that. Also, in your environment it seems there will be many more people calling the function than changing it, so it can be quite assured the input will not be unduely modified, and you can ignore the warning altogether.

For ignoring this specific warning check here for GCC, other compilers also provide this options.

About the const on function parameter input check here, I particularly like this answer: "If your code has many people working on it and your functions are non-trivial then you should mark const any and everything that you can. When writing industrial-strength code, you should always assume that your coworkers are psychopaths trying to get you any way they can (especially since it's often yourself in the future).".

Arc
  • 412
  • 2
  • 16