Function-types: compatability, and typedefs

Doug Gwyn gwyn at smoke.BRL.MIL
Sun Sep 3 08:38:42 AEST 1989


In article <KERS.89Aug31163340 at cdollin.hpl.hp.com> kers at hpld.hpl.hp.com (Kers) writes:
>	qsort( Base, NMembers, Size, strcmp );
>... is strcmp suitable for passing as an argument
>    - without explicit casting?
>    - with explicit casting?
>    - ever?

I don't think it has a type compatible with the declared parameter for qsort.
Therefore it violated the pANS semantic constraints.  However, casting it to
the appropriate type is allowed, and having done so it will actually work
since the pANS requires char* and void* to be represented identically.
In fact this specific example motivated the current pANS wording about these
matters.

What I do, though, is provide my own function that receives generic pointers
and cast them as needed inside that function.  It doesn't place quite so
much trust in the implementation, and if I change from char* strings to
counted strings, for example, it facilitates making the change (the cast at
qsort invocation approach would no longer be valid in such a case).

>Second, about typedefs for function types. I'd like to be able to declare a
>type for a function, so that I can use it for declaring arguments. I'm a
>little unclear about how I do so.
>
>    typedef char * (char *) MonadicStringFunction;
>
>As I read the pANS (DEC 1988, Section 3.5.5), that would be OK; the type's a
>function declarator with the name omitted.

I haven't tried to figure out how you read the pANS, but typedefs work as
follows (and if the pANS says otherwise, it's broken):

	typedef	<normal declarator INCLUDING an identifier>;
	/* now the identifier has that type */

So your example should be written

	typedef char *MonadicStringFunction(char *);

Just now I looked up the pANS grammar, and "typedef" is treated grammatically
as just a storage class specifier (like "register").  I think you must have
been looking at the syntax for type names, which have nothing to do with
typedef.  (Think of a type name as the part of a cast between the parentheses.)

>    extern int example( MonadicStringFunction arg );
>Would I need to add the * to ensure the argument is treated as a function 
>pointer...

I think so.  You want a pointer to a function, you should declare it as such.
The automatic conversion of identifier designating a function to a pointer
occurs only in expressions, not in declarations.  For usage exactly as you
show in the example, you need the typedef:

	typedef char *(*MonadicStringFunction)(char *);

If you wanted to retain the previous declaration (which might be more
convenient), then declare example like this:

	extern int example( MonadicStringFunction *arg );

>Can I also use the typedef in a *definition*:
>    MonadicStringFunction boring( char *arg ) { return arg; }

With the first (non-pointer) typedef, you're supposed to be able to.
Some compilers have historically had trouble handling this kind of usage,
though.

>Finally, I was going to post this to comp.std.c, but decided it wasn't
>discussion "about" the standard. Would that have been a more appropriate
>place?

Only insofar as you're reporting difficulty extracting this information
from the pANS.  However, typedefs predate the pANS so this is a general
C usage issue for the most part.  (Compatibility of function arguments
is Standard C specific.)



More information about the Comp.lang.c mailing list