2

Is it purely style that you can declare a function-reference parameter like,

int g ( int (*f)(int,int) ) {

Or

int g ( int f(int,int) ) {

In my limited experience with C, I've never seen the prototype-method.

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
Evan Carroll
  • 78,363
  • 46
  • 261
  • 468
  • As a reference, the C11 spec for `qsort()` uses `void qsort(void *base, size_t nmemb, size_t size, int (*compar)(const void *, const void *));`. Closer to the `int (*f)(int,int)`. Interestingly `qsort_s()` uses _named_ parameters `..., int (*compar)(const void *x, const void *y, void *context), ...` – chux - Reinstate Monica Aug 15 '18 at 00:17

2 Answers2

4

I suppose it is style, but the explicit pointer to function notation aligns with ancient practice and with the way the compiler interprets the code.

The C11* standard says in §6.7.6.3 Function declarators (including prototypes) ¶8:

¶8 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 Lvalues, arrays and function designators ¶4 says:

¶4 A function designator is an expression that has function type. Except when it is the operand of the sizeof operator, the _Alignof operator,65) 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".

65) Because this conversion does not occur, the operand of the sizeof or _Alignof operator remains a function designator and violates the constraints in 6.5.3.4.

Using the pointer notation, therefore, shows explicitly what the compiler will do anyway. (I still usually invoke explicit pointers to functions using the (*function_ptr)(arg1, …, argN) notation, even though function_ptr(arg1, …, argN) also works.)


* The C18 standard is current, but there isn't a convenient online HTML version of it available as yet. Mostly, the two are very similar. As it happens, §6.3.2.1 ¶4 is one paragraph with a difference — the C18 version doesn't mention _Alignof.

Community
  • 1
  • 1
Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
  • ..and if we are talking "ancient practice" my K&R Ref Manual (1978) para 14.2 states "If the name of a function appears in an expression ... a pointer to the function is generated" :-) – bcperth Aug 15 '18 at 00:51
  • “The standard” is now C 2018, not C11, and I suspect the text you cite is altered, as `_Alignof` cannot grammatically be applied to a function identifier. – Eric Postpischil Aug 15 '18 at 03:27
  • @EricPostpischil:Yes, but the link is to the C11 standard. I can't justify the spending preposterous price of the C18 standard — maybe I should start a GoFundMe campaign? I'm quoting the standard I identify. When there's an online version of C18, I'll link to that instead. – Jonathan Leffler Aug 15 '18 at 04:26
  • @JonathanLeffler: [This answer](https://stackoverflow.com/a/83763/298225) is updated with the current standards and drafts, including a link to a draft for C 2018 which shows that, indeed, this text is changed. I am sympathetic to the cost issues for students and amateurs. I also support using appropriate versions of the standard or using non-standard behavior for questions for which that is suitable, going agains the prevailing current in Stack Overflow. However, the description for the C tag favors using the latest standard, and so does the community generally… – Eric Postpischil Aug 15 '18 at 04:51
  • … and moving along with the standard as versions are published helps to support the purposes of standardization. The more people are using the latest version, the more compiler developers will be inclined to conform to it, so improvements in portability, new features, quality of conformance will tend to come sooner. – Eric Postpischil Aug 15 '18 at 04:52
  • Why is the PDF draft not acceptable? Hyperlinks are nice for direct references but are not crittical, and I do not find documents segmented for the web conducive to reading and learning. – Eric Postpischil Aug 15 '18 at 05:11
  • 1
    C18 seems to be counterproductive for those working with the huge existing C99 + POSIX.1 codebase. It seems the C standard is being pushed in an odd direction, as if some of those working on the standard wish for C to include some, but not all necessary parts of POSIX.1 to be practically functional. None of the non-Windows C programmers I've talked to seem to be keen on jumping on C18; most seem to be, like myself, using C99 plus POSIX.1 plus a small subset of C11. It is a pity you std devs don't listen to the developer community. – Nominal Animal Aug 15 '18 at 05:16
  • @NominalAnimal: I do not know who the “you” you are addressing is; I did not participate in the C standard process. C is largely mature, but, generally, standards meetings are accessible to the public, and individuals can participate iin variouus ways. If you have issues that matter to you, you should be participating. – Eric Postpischil Aug 15 '18 at 05:40
  • @EricPostpischil: From your comments I assumed you were one of those paid to work on the C standard; I apologise. No, the committee is stuffed with company representatives, and non-big-money affiliated individuals have approximately 0.0% chance of affecting any decision. (It's not just companies, though; it seems that committees just don't work. Even Linux kernel devs have issues with GCC developers when GCC generates stupid code because the standard says they're allowed to, even when there is a clear practical reason to provide sane behaviour.) – Nominal Animal Aug 15 '18 at 06:12
0

The name of a function f IS a pointer to function f. ie the compiler treats them identically. You can use the 2 forms interchangeably, in the context of your questions.

However, in the interest of completeness, see the exceptions in cases of sizeof operator, the _Alignof operator,65) and the unary & as correctly pointed out in Jonathan Leffler's most complete answer.

Both of your statements say: g is a function returning int, whose parameter is a pointer to a function f returning int whose parameters and int, int.

Evan Carroll
  • 78,363
  • 46
  • 261
  • 468
bcperth
  • 2,191
  • 1
  • 10
  • 16
  • 1
    This is not exactly true. The identifier of a function has type "function returning void" or "function returning ", not *pointer to* one of those. But such an identifier is *converted to* a function pointer in moist contexts. This is in many ways analogous to arrays, including that one of the places where you can see a difference is the `sizeof` operator. It is a constraint violation to apply `sizeof` to an expression of function type, but you can apply it freely to function pointers. – John Bollinger Aug 15 '18 at 00:54