George <> writes:
> I'm working on an old (comment-free) program, and finding some of the
> code is above my pay grade. I'd appreciate insight into what's going on
> with the segment below.
>
> -----------------
> #define SCRN_LIST \
> SCRN(Null) \
> SCRN(RYG) \
> SCRN(Fr00) \
> SCRN(LastN) \
> SCRN(DateTime) \
>
> #define INIT_LIST \
> INIT(Default) \
> INIT(LastN) \
> INIT(EvtLog) \
> INIT(EvtLogDetail) \
>
> typedef void (*VOID_FNC)(void);
>
> #define SCRN(symm) (const VOID_FNC)symm##ScrnFnc,
> #define INIT(symm) (const VOID_FNC)symm##InitFnc,
> const VOID_FNC ScrnFnc[] = {
> SCRN_LIST
> INIT_LIST
> };
> #undef SCRN
> #undef INIT
>
> // typical fnc
>
> void
> NullScrnFnc(void) { ... }
> -----------------
>
> I think the final result wants to be ...
> const void (*ScrnFnc[])() = {
The type is actually
void (*const ScrnFnc[])(void)
Your () is not quite the same as (void), and the const refers to the
whole pointer type -- i.e. the elements of the array are read-only. In
your version, what is const is the returned type of the functions
pointer to by the array elements and one never writes such things.
Writing
const int f(void);
is pointless. Of course one often sees
const char *f(void);
or
char const *f(void);
but here what is const is the pointed-to type: f is a function returning
a pointer to const char (or char const). A function returning a const pointer
type is never written:
char *const f(void);
Once the programmer has defined the "pointer to function type" called
VOID_FNC, making *that* const applies to the pointers in the array.
Adding the the fact that ScrnFnc is an array makes the type harder to
write but all C types are easy to readif you know the trick. This is
such a common issue that I've put a page up about this:
http://bsb.me.uk/c-types
> NullScrnFnc,
> RYGScrnFnc,
> ...
> DefaultInitFnc,
> LastNInitFnc,
> ...
> };
The result is actually
const VOID_FNC ScrnFnc[] = {
(const VOID_FNC)NullScrnFnc,
(const VOID_FNC)RYGScrnFnc,
...
(const VOID_FNC)DefaultInitFnc,
(const VOID_FNC)LastNInitFnc,
...
};
because VOID_FNC is a typedef and so not "expanded", but I know what you
meant.
> Even assuming that's correct, I don't see how it gets there. I see that
> SCRN_LIST/INIT_LIST will cause ea of their listed arguments (Null, RYG,
> etc) to instantiate the 'SCRN'/'INIT' macros in the ScrnFnc[]
> declaration, But, ISTM, this would create something like (eg) ...
> void (*NullFnc)()
Hmmm... not sure why you say that so I can't readily help. The typedef
is not expanded, of course. Maybe that's part of the confusion?
> Bonus points: I don't know how to 'read' the VOID_FNC typedef. I think
> that's a standard construct (ptr to void fnc?), but the logic of it
> eludes me.
Does my linked page help with that?
--
Ben.