Обсуждение: style for typedef of function that will be pointed to
Hi, From everything I've seen, the PostgreSQL style seems to be to include the * in a typedef for a function type to which pointers will be held: typedef void (*Furbinator)(char *furbee); struct Methods { Furbinator furbinate; }; An alternative I've sometimes used elsewhere is to typedef the function type itself, and use the * when declaring a pointer to it: typedef void Furbinator(char *furbee); struct Methods { Furbinator *furbinate; }; What I like about that form is it allows reusing the typedef to prototype any implementing function: static Furbinator _furbinator0; static void _furbinator0(char *furbee) { } It doesn't completely eliminate repeating myself, because the function definition still has to be spelled out. But it's a bit less repetitive, and makes it visibly explicit that this function is to be a Furbinator, and if I get the repeating-myself part wrong, the compiler catches it right on the spot, not only when I try to assign it later to some *Furbinator-typed field. Use of the thing doesn't look any different, thanks to the equivalence of a function name and its address: methods.furbinate = _furbinator0; Naturally, I'm not proposing any change of existing usages, nor would I presume to ever submit a patch using the different style. If anything, maybe I'd consider adding some new code in this style in PL/Java, which as an out-of-tree extension maybe isn't bound by every jot and tittle of PG style, but generally has followed the documented coding conventions. They seem to be silent on this one point. So what I'm curious about is: is there a story to how PG settled on the style it uses? Is the typedef-the-function-itself style considered objectionable? For any reason other than being different? If there were compilers at one time that didn't like it, are there still any? Any that matter? I've found two outside references taking different positions. The Ghostscript project has coding guidelines [0] recommending against, saying "Many compilers don't handle this correctly -- they will give errors, or do the wrong thing, ...". I can't easily tell what year that guideline was written. Ghostscript goes back a long way. The SquareSpace OpenSync coding standard [1] describes both styles (p. 34) and the benefits of the typedef-the-function-itself style (p. 35), without seeming to quite take any final position between them. Regards, -Chap [0] https://www.ghostscript.com/doc/9.50/C-style.htm [1] https://www.opensync.io/s/EDE-020-041-501_OpenSync_Coding_Standard.pdf
Chapman Flack <chap@anastigmatix.net> writes: > From everything I've seen, the PostgreSQL style seems to be to include > the * in a typedef for a function type to which pointers will be held: > typedef void (*Furbinator)(char *furbee); Yup. > An alternative I've sometimes used elsewhere is to typedef the function > type itself, and use the * when declaring a pointer to it: > typedef void Furbinator(char *furbee); Is that legal C? I doubt that it was before C99 or so. As noted in the Ghostscript docs you came across, it certainly wouldn't have been portable back in the day. > So what I'm curious about is: is there a story to how PG settled on > the style it uses? See above. regards, tom lane
On 10/05/21 13:47, Tom Lane wrote: >> An alternative I've sometimes used elsewhere is to typedef the function >> type itself, and use the * when declaring a pointer to it: >> typedef void Furbinator(char *furbee); > > Is that legal C? I doubt that it was before C99 or so. As noted > in the Ghostscript docs you came across, it certainly wouldn't have > been portable back in the day. It compiles silently for me with gcc --std=c89 -Wpedantic I think that's the oldest standard I can ask gcc about. Per the manpage, 'c89' is ISO C90 without its amendment 1, and without any gnuisms. Regards, -Chap
On 10/05/21 14:00, Chapman Flack wrote: > On 10/05/21 13:47, Tom Lane wrote: >>> An alternative I've sometimes used elsewhere is to typedef the function >>> type itself, and use the * when declaring a pointer to it: >>> typedef void Furbinator(char *furbee); >> >> Is that legal C? I doubt that it was before C99 or so. As noted >> in the Ghostscript docs you came across, it certainly wouldn't have >> been portable back in the day. > > It compiles silently for me with gcc --std=c89 -Wpedantic > > I think that's the oldest standard I can ask gcc about. Per the manpage, > 'c89' is ISO C90 without its amendment 1, and without any gnuisms. There are some places in the tree where AssertVariableIsOfType is being cleverly used to achieve the same thing: void _PG_output_plugin_init(OutputPluginCallbacks *cb) { AssertVariableIsOfType(&_PG_output_plugin_init, LogicalOutputPluginInit); void _PG_archive_module_init(ArchiveModuleCallbacks *cb) { AssertVariableIsOfType(&_PG_archive_module_init, ArchiveModuleInit); While clever, doesn't it seem like a strained way to avoid just saying: typedef void ArchiveModuleInit(ArchiveModuleCallbacks *cb); ArchiveModuleInit _PG_archive_module_init; void _PG_archive_module_init(ArchiveModuleCallbacks *cb) { if indeed compilers C90 and later are happy with the straight typedef? Not that one would go changing existing declarations. But perhaps it could be on the table for new ones? Regards, -Chap