variadic functions and terminating null pointer

Vincent Lefevre vincent at vinc17.net
Sun Feb 12 22:25:37 CET 2012


The GMP 5.0.4 manual says:

@deftypefun void mpz_inits (mpz_t @var{x}, ...)
Initialize a NULL-terminated list of @code{mpz_t} variables, and set their
values to 0.
@end deftypefun

@deftypefun void mpz_clears (mpz_t @var{x}, ...)
Free the space occupied by a NULL-terminated list of @code{mpz_t} variables.
@end deftypefun

Ditto for mpq and mpf.

However, for variadic functions, the implementation cannot convert
the arguments to the expected type. This means that the user must
provide arguments with a type compatible with the expected type
(e.g. mpz_t *); in particular this will imply that the types have
the same representation.

Concerning NULL, the C standard says:

    6.3.2.3 Pointers

 3  An integer constant expression with the value 0, or such an expression
    cast to type void *, is called a null pointer constant.66) [...]

    66) The macro NULL is defined in <stddef.h> (and other headers) as a
        null pointer constant; see 7.19.

So, NULL can be defined as the integer 0. Thus terminating the list
with NULL may have unexpected behavior if 0 and the expected pointer
type do not have the same representation (e.g. 32-bit int vs 64-bit
pointers). Even if NULL is defined as (void *) 0, the code may be
incorrect, as the expected type is mpz_t *. Indeed, the C standard
says:

    6.2.5 Types

28  A pointer to void shall have the same representation and alignment
    requirements as a pointer to a character type.48) Similarly, pointers
    to qualified or unqualified versions of compatible types shall have
    the same representation and alignment requirements. All pointers to
    structure types shall have the same representation and alignment
    requirements as each other. All pointers to union types shall have
    the same representation and alignment requirements as each other.
    Pointers to other types need not have the same representation or
    alignment requirements.

See the last sentence in particular.

Even if the types have the same representation, one can get unexpected
behavior due to the fact that compilers optimize more and more.

So, the last argument of mpz_inits and mpz_clears should be (mpz_t *) 0
or equivalent. Similar rules for mpq and mpf.

-- 
Vincent Lefèvre <vincent at vinc17.net> - Web: <http://www.vinc17.net/>
100% accessible validated (X)HTML - Blog: <http://www.vinc17.net/blog/>
Work: CR INRIA - computer arithmetic / AriC project (LIP, ENS-Lyon)


More information about the gmp-bugs mailing list