Passing NULL as a function pointer

S

Spiros Bousbouras

The following code by Keith Thompson is being referred to below :

typedef void (*funcptr)(void);

void func(funcptr arg)
{
if (arg) {
arg();
}
}

[In the quote below I've changed some non ASCII Unicode to ASCII.]

Since you didn't show us the full source of the program, we can't be
100% sure of what's going on. What happens when you compile this?
[...]

The warning comes again out...

That seems to be non-standard behavior.

What happens if you compile Keith's example program, but with the line
func((void*)0);
replaced with
func(0);
- does that work better?

According to the standard (6.3.2.3 p3), the following holds:

int main(void)
{
func(0); // should work
func((void*)0); // should also work, but your system is non-standard

How do you mean "non-standard" ? It seems to me it will work on every
conforming implementation.
func(NULL); // resolves to either of the foregoing; should work

NULL could also be 0U or 0UL or (void*)0U or many other things.
void *null = 0;
func(null); // should *not* work

Do you mean it's undefined behavior (which it is) or that realistically
you wouldn't expect it to work ?
func((funcptr)null); // often permitted (common extension J.5.7),
// but not portable, nor guaranteed to work as
// expected even if it compiles
return 0;
}

[...]
 
K

Keith Thompson

Spiros Bousbouras said:
The following code by Keith Thompson is being referred to below :

typedef void (*funcptr)(void);

void func(funcptr arg)
{
if (arg) {
arg();
}
}

[In the quote below I've changed some non ASCII Unicode to ASCII.]

Since you didn't show us the full source of the program, we can't be
100% sure of what's going on. What happens when you compile this?
[...]

The warning comes again out...

That seems to be non-standard behavior.

What happens if you compile Keith's example program, but with the line
func((void*)0);
replaced with
func(0);
- does that work better?

According to the standard (6.3.2.3 p3), the following holds:

int main(void)
{
func(0); // should work
func((void*)0); // should also work, but your system is non-standard

How do you mean "non-standard" ? It seems to me it will work on every
conforming implementation.

Exactly. The OP's compiler issues a warning on that line, which doesn't
violate the standard (compilers can issue whatever diagnostics they
like), but I would consider it a bug.
NULL could also be 0U or 0UL or (void*)0U or many other things.

Yes, any null pointer constant should be valid.
Do you mean it's undefined behavior (which it is) or that realistically
you wouldn't expect it to work ?

It's a constraint violation. There's no implicit conversion from
void* to any pointer-to-function type.

[...]
 
S

Spiros Bousbouras

It's a constraint violation. There's no implicit conversion from
void* to any pointer-to-function type.

Yes but a constraint violation can still give an executable which works
hence my uncertainty as to what "should *not* work" means.
 
K

Keith Thompson

Spiros Bousbouras said:
Yes but a constraint violation can still give an executable which works
hence my uncertainty as to what "should *not* work" means.

The only requirement on an implementation when it enounters a
violation of a syntax rule or a constraint is that it must issue a
diagnostic (actually at least one diagnostic for any translation
unit containing one or more such violations). It *can* go on to
generate an executable, whose behavior is then undefined.

But in most cases, the source file fails to compile, and IMHO that's
what implementations *should* do in most or all cases.

An implementation is certainly *permitted* to reject translation units
with such violations.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,755
Messages
2,569,534
Members
45,007
Latest member
obedient dusk

Latest Threads

Top