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