Can I reliably set a function pointer to NULL in C and C++?

17,376
 int (*pfun) (void) = NULL;  

It is actually valid.

The C rules of assignment says that:

(Note that's an initialization here but the same type of constraints and conversions as for simple assignment apply.)

(C99, 6.5.16.1 Simple assignment p1 Constraints) "One of the following shall hold: [...] — the left operand is a pointer and the right is a null pointer constant;"

and

(C99, 7.17p3) "The macros are NULL which expands to an implementation-defined null pointer constant;"

So assigning a null pointer constant to any pointer (object pointer, function pointer or void *) is allowed by C. Note that Plauger's book refers to C89 when he mentions Standard C but the wording of the assignment constraints are the same in C89.

Share:
17,376
rationalcoder
Author by

rationalcoder

I love most things computer science. I write code every day for fun or for my day job.

Updated on June 05, 2022

Comments

  • rationalcoder
    rationalcoder about 2 years

    In P.J. Plauger's book, The Standard C Library, he warns about assigning a function pointer to NULL.

    Specifically, he says this:

    The macro NULL serves as an almost-universal null pointer constant. You use it as the value of a data-object pointer that should point to no data object declared (or allocated) in the program. As I mentioned on page 216, the macro can have any of the following definitions 0, 0L, or (void *)0.

    The last definition is compatible with any data object pointer. It is not, however, compatible with a function pointer. That means you cannot write

    int (*pfun) (void) = NULL; /* WRONG */

    The translator may complain that the expression type is incompatible with the data object you wish to initialize.

    He goes on to say that:

    ...There is no guarantee, however, that a pointer to void has the same representation as any other (non-character) pointer. It isn't even assignment compatible with function pointers. That means that you can't write NULL as a universal null-pointer constant. Nor can you safely use it as an argument expression in place of an arbitrary data-object pointer.

    I have been assigning function pointers to NULL for quite some time without any problems, and I am wondering if it isn't portable.

    Specifically:

    void (*test)() = NULL => compiles fine with both gcc and g++

    void (*test)() = 0 => compiles fine with both gcc and g++

    void (*test)() = (void*)0 => produced an invalid conversion error in both gcc and g++

    EDIT: void (*test)() = (void*)0compiles fine in gcc, I was using a file with a .cpp extension... Still, will it always compile, despite Plauger saying that assigning a function pointer to NULL is wrong?

    The part I don't understand is the definition of NULL in my stddef.h:

    #if defined (_STDDEF_H) || defined (__need_NULL)
    #undef NULL     /* in case <stdio.h> has defined it. */
    #ifdef __GNUG__
    #define NULL __null
    #else   /* G++ */
    #ifndef __cplusplus
    #define NULL ((void *)0) // this line confuses me
    #else   /* C++ */
    #define NULL 0
    #endif  /* C++ */
    #endif  /* G++ */
    #endif  /* NULL not defined and <stddef.h> or need NULL.  */
    #undef  __need_NULL
    

    This seems to be defining NULL to be 0 in C++ and ((void *)0) in C. Is it really, or is it being defined as __null?

    If so, why does assigning to NULL work all the time, even though assigning to (void*)0, according to Plauger, is "wrong"?**

    I am interested in C89**