Home > Enterprise >  Typedef (anonymous) struct array of size 1
Typedef (anonymous) struct array of size 1

Time:10-27

So recently I've been poking around in the internals of GMP for a project I'm working on, and I've encountered a construct that makes very little sense to me: (taken from the header for version 6.2.1)

/* For reference, note that the name __mpz_struct gets into C   mangled
   function names, which means although the "__" suggests an internal, we
   must leave this name for binary compatibility.  */
typedef struct
{
  int _mp_alloc;        /* Number of *limbs* allocated and pointed
                   to by the _mp_d field.  */
  int _mp_size;         /* abs(_mp_size) is the number of limbs the
                   last field points to.  If _mp_size is
                   negative this is a negative number.  */
  mp_limb_t *_mp_d;     /* Pointer to the limbs.  */
} __mpz_struct;

#endif /* __GNU_MP__ */


typedef __mpz_struct MP_INT;    /* gmp 1 source compatibility */
typedef __mpz_struct mpz_t[1];

On the final line here, we typedef mpz_t to be an array of size 1 containing __mpz_structs. This is very strange to me, and I've never seen a construction like this before. I understand that this results in mpz_t effectively being a pointer to an __mpz_struct, but is this equivalent or not to

typedef __mpz_struct* mpz_t;

Could somebody explain the logic behind this?

CodePudding user response:

With that typedef, a variable declaration like

mpz_t foo;

is equivalent to

__mpz_struct foo[1];

This will only be converted to

__mpz_struct *foo;

if the declaration is in a function parameter list. Otherwise, it's a ordinary array declaration.

CodePudding user response:

Given typedef __mpz_struct mpz_t[1];, you can declare an actual mpz_t object with mpz_t foo;. This will reserve memory for an mpz_t.

In contrast, if the type were typedef __mpz_struct *mpz_t;, then mpz_t foo; would only give you a pointer. There would be no space for an mpz_t. You would have to allocate it, and you would have to free it later. So more code is required, and it would be a nuisance.

At the same time, when an mpz_t is passed to a function, only its address is passed, due to the automatic conversion of arrays to pointers. This allows writing mpz_add(z, x, y);, which is less cluttered than mpz_add(&z, &x, &y);. There may be arguments among programmers about whether it is bug-prone to use a type definition that effectively results in a reference to an object being passed to a function when the code nominally looks like just a value is passed, but this style may be more suitable for the type of programming done with GMP.

  • Related