FrozenHeart
FrozenHeart

Reputation: 20736

Casts between pointer-to-function and pointer-to-object in C and C++

Am i wrong about the following?

C++ standards says that conversion between pointer-to-function and pointer-to-object (and back) is conditionnaly-supported with implementation-defined semantics, while all C standards says that this is illegal in all cases, right?

void foo() {}

int main(void)
{
    void (*fp)() = foo;
    void* ptr = (void*)fp;
    return 0;
}

ISO/IEC 14882:2011

5.2.10 Reinterpret cast [expr.reinterpret.cast]

8 Converting a function pointer to an object pointer type or vice versa is conditionally-supported. The meaning of such a conversion is implementation-defined, except that if an implementation supports conversions in both directions, converting a prvalue of one type to the other type and back, possibly with different cvqualification, shall yield the original pointer value.

I can't find anything about it in C standard right now...

Upvotes: 16

Views: 7797

Answers (5)

Chris Dodd
Chris Dodd

Reputation: 126185

The POSIX standard specifies:

2.12.3 Pointer Types
All function pointer types shall have the same representation as the type pointer to void. Conversion of a function pointer to void * shall not alter the representation. A void * value resulting from such a conversion can be converted back to the original function pointer type, using an explicit cast, without loss of information.

Note: The ISO C standard does not require this, but it is required for POSIX conformance.

This requirement ends up meaning that any C or C++ compiler that wants to be able to support POSIX will support this kind of casting.

Upvotes: 1

effeffe
effeffe

Reputation: 2881

Though the behavior of the cast is not defined by the "core" of the standard, this case is explicitly described as invalid in the C99 rationale document (6.3.2.3, Pointers):

Nothing is said about pointers to functions, which may be incommensurate with object pointers and/or integers.

Even with an explicit cast, it is invalid to convert a function pointer to an object pointer or a pointer to void, or vice versa.

And since it may be useful, it is also mentioned in the Annex J of the standard as a "common extension" (C11 Standard J.5.7, Function pointer casts):

A pointer to an object or to void may be cast to a pointer to a function, allowing data to be invoked as a function (6.5.4).

A pointer to a function may be cast to a pointer to an object or to void, allowing a function to be inspected or modified (for example, by a debugger) (6.5.4).

Describing this as an extension means that this is not part of the standard requirements (but it wouldn't be needed, the omission of any explicit behavior is enough).

Upvotes: 5

David Hammen
David Hammen

Reputation: 33106

  • In C++03, such conversions were illegal (not UB). The compiler was supposed to issue a diagnostic. A lot of compilers on Unix systems didn't issue a diagnostic. This was essentially a clash between standards, POSIX vs C++.
  • In C++11, such conversions are "conditionally supported". No diagnostic is required if the system does supports such conversions; there's nothing to diagnose.
  • In C, such conversions officially are undefined behavior, so no diagnostic is required. If the system happens to do the "right" thing, well that's one way to implement UB.
  • In C99, this is once again UB. However, the standard also lists such conversions as one of the "common extensions" to the language:

    J.5.7 Function pointer casts
    A pointer to an object or to void may be cast to a pointer to a function, allowing data to be invoked as a function (6.5.4).
    A pointer to a function may be cast to a pointer to an object or to void, allowing a function to be inspected or modified (for example, by a debugger) (6.5.4).

Upvotes: 13

AProgrammer
AProgrammer

Reputation: 52274

In all C standards the conversion between pointer-to-function and pointer-to-object is not defined, in C++ before C++11, the conversion was not allowed and compilers had to give an error, but there were compilers which accepted the conversion for C and backward compatibility and because is useful for things like dynamically loaded libraries access (for instance the dlsym POSIX function mandates its use). C++11 introduced the notion of conditionally-supported features an used it to adapt the standard with the existing practice. Now either the compiler should reject the program trying to do such conversion or it should respect the limited constraints given.

Upvotes: 5

Oliver Charlesworth
Oliver Charlesworth

Reputation: 272467

You're right, the C(99) standard says nothing about conversion from pointer-to-function to pointer-to-object, therefore it's undefined behaviour.*


*Note, however, that it does define behaviour between pointer-to-function types.

Upvotes: 9

Related Questions