Path: utzoo!utgpu!jarvis.csri.toronto.edu!mailrus!uflorida!haven!adm!smoke!gwyn From: gwyn@smoke.BRL.MIL (Doug Gwyn) Newsgroups: comp.lang.c Subject: Re: Function-types: compatability, and typedefs Message-ID: <10910@smoke.BRL.MIL> Date: 2 Sep 89 22:38:42 GMT References: Reply-To: gwyn@brl.arpa (Doug Gwyn) Organization: Ballistic Research Lab (BRL), APG, MD. Lines: 75 In article kers@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 ; /* 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.)