Keith Thompson said:
Where does the standard say that a conversion between a function
pointer and an object pointer, even with an explicit cast, is allowed?
(C99 6.3.2.3 discusses conversions between a pointer to an object or
incomplete type and a pointer to a different object or incomplete
type, and conversions between different pointer-to-function types, but
there's no mention of conversions between pointer-to-object types and
pointer-to-function types.) Or is it implicitly allowed (with
undefined behavior) because the standard doesn't disallow it?
[...]
What I was really looking for was an explicit statement about which
conversions are legal and which are not, particularly those involving
pointer types. (By "legal", I mean not requiring a diagnostic.)
C99 6.3.2.3 enumerates a number of kinds of conversions that are
allowed (it uses the phrase "may be converted"). (6.3.1 discusses
arithmetic operands.) Some potential conversions are not enumerated,
for example conversions between pointer types and floating-point
types; such conversions are unlikely to make much sense on most
implementations, but it seemed odd to me that they aren't mentioned.
I was also wondering about even less sensible conversions, such as
between pointers and structs.
The piece of the puzzle that I was missing was 6.5.4, "Cast
operators":
Unless the type name specifies a void type, the type name shall
specify qualified or unqualified scalar type and the operand shall
have scalar type.
Conversions that involve pointers, other than where permitted by
the constraints of 6.5.16.1, shall be specified by means of an
explicit cast.
I think this means that conversion between a pointer type and a
floating-point type does not require a diagnostic (it doesn't violate
any constraint), but it invokes undefined behavior, since the standard
doesn't define what the behavior is. On the other hand, conversion
between a pointer type and a struct type is illegal; an explicit cast
is not allowed because one of the types is not scalar, and there's no
way to do the conversion implicitly.
I've tried the following program with several C compilers:
int main(void)
{
double dbl = 0.0;
int *ptr;
ptr = (int*)dbl;
return 0;
}
The assignment, if I'm correct, is legal but invokes undefined
behavior. Every compiler I've tried prints a diagnostic and rejects
the program:
error: cannot convert to a pointer type
invalid cast expression
The indicated type conversion is invalid.
"double" cannot be converted to "int*".
In this statement, "dbl" is of type "double", and cannot be
converted to "pointer to int"
I suppose printing a diagnostic and rejecting the program is a valid
consequence of undefined behavior, but it's not something that most
compilers generally do. Most C compilers typically print at most a
warning for undefined behavior, but don't reject the program.
The behavior of any one compiler, or even of any five compilers, is
not of course definitive in interpreting the standard, but it does
appear that the implementers of those compilers thought that
converting a floating-point value to a pointer type is illegal.
Is there a statement in the C standard that a conversion from a
floating-point type to a pointer type is a constraint violation?
I acknowledge that this isn't a particularly practical question unless
you're writing a compiler; it wouldn't occur to most of us to try to
convert a floating-point value to a pointer type in the first place.