Function notation for function pointer parameters in ISO C Standard

73 Views Asked by At

I was reading the draft of the third edition of "Modern C" by Jens Gustedt and came across a paragraph discussing the use of function notation for function pointer parameters.

Specifically, it states that using function notation emphasizes, semantically, that a null function pointer as an argument is not allowed:

/* This  emphasizes  that  the ˋˋhandler’’ argument  cannot  be null. */
int  atexit(void handler(void));
/*  Compatible  declaration  for  the  same  function.                */
int  atexit(void(* handler)(void));

However, upon examining the 3220n draft, I couldn't find any mention of this specific notation or its implications. Compiling the code with GCC trunk version doesn't yield any warnings either.

Does the use of "semantically" in the paragraph imply that this notation is merely a developer esoteric convention or is it actually defined somewhere in the C standard?

2

There are 2 best solutions below

0
Eric Postpischil On BEST ANSWER

There is no distinction between these two declarations in the C standard. The first is automatically adjusted to be the second, making them functionally identical in the standard.

The notion that the first conveys any intention for the pointer not to be null is entirely outside the C standard. It is a personal opinion about coding style and is one I have not seen or heard of previously. It would be hazardous to rely on it.

0
nielsen On

From a C standard point of view, the declarations are equivalent.

C17 6.7.6.3-8 says:

A declaration of a parameter as “function returning type” shall be adjusted to “pointer to function returning type”, as in 6.3.2.1.

And 6.3.2.1-4:

A function designator is an expression that has function type. Except when it is the operand of the sizeof operator,66) or the unary & operator, a function designator with type “function returning type” is converted to an expression that has type “pointer to function returning type”.

Thus, the compiler shall not issue a diagnostic message if a null pointer is passed as an argument where the type is a function.

The word "semantically" probably means that this is an indication to the human reader of the code.

As a side note, the GCC compiler supports the attribute nonnull for making the compiler check if a null pointer is passed as argument. Thus declaring the function as follows:

__attribute__((nonnull (1))) int atexit(void handler(void));

and building with -Wnonnull will issue a warning if the function is called with NULL:

  atexit(NULL);  <-- Warning: argument 1 null where non-null expected

However, this only seems to apply to a null pointer literal, not a variable even though it may obviously be a null pointer in the given context:

  void (*f)(void) = NULL;
  atexit(f);   <-- No warning