Relay-Version: version B 2.10 5/3/83; site utzoo.UUCP Posting-Version: version B 2.10.2 9/18/84; site ucsfcgl.UUCP Path: utzoo!watmath!clyde!burl!ulysses!allegra!mit-eddie!genrad!decvax!ucbvax!ucsfcgl!arnold From: arnold@ucsfcgl.UUCP (Ken Arnold%CGL) Newsgroups: net.lang.c Subject: Function pointer syntax peculiarity Message-ID: <396@ucsfcgl.UUCP> Date: Tue, 27-Nov-84 14:22:08 EST Article-I.D.: ucsfcgl.396 Posted: Tue Nov 27 14:22:08 1984 Date-Received: Fri, 30-Nov-84 05:51:10 EST References: <5367@brl-tgr.UUCP> <7200003@hpdsa.UUCP> <271@ukma.UUCP> <423@kcl-cs.UUCP> <226@desint.UUCP> <1461@drutx.UUCP> Reply-To: arnold@ucsfcgl.UUCP (PUT YOUR NAME HERE) Organization: UCSF Computer Graphics Lab Lines: 82 Summary: Looking at the code for qsort(), I came across the following peculiarity in the syntax and semantics of function pointers. It seems that "(*cfunc)()" and "cfunc()" are both equivalent uses of a pointer to a function "cfunc". qsort takes, as it's fourth parameter, a pointer to a function. Below is a piece of sample pseudo code extern int cmp(); ... qsort(, <# of elements>, , cmp); ... The qsort declaration is qsort(base, nel, width, cfunc) char *base; int nel, width; int (*cfunc)(); { ... } I have used pointers to functions, and the way I use them is (*cfunc)(...); /* call this syntax 1 */ However, qsort() uses it like this: cfunc(...); /* call this syntax 2 */ which seems to work. I have tested the code on our 4.2bsd C compiler (a version of PCC) and both usages generate the same code, and neither gives a warning message. Now, having "*f" and "f" mean the same thing doesn't fit into the normal meaning of unary "*", so which is right? This sends me scurrying to K&R, which uses syntax 1 in all it's examples. I have also always used this sytax. But after thinking about it (always a dangerous thing to do :->), it seems to me that syntax 2 is more consistent with the semantics of the thing. Consider how you declare that cfunc() is a function, and how you get the pointer out of that declaration. The following is typical (equivalent code for an array is presented on the side for reasons which will be clear below): int cfunc(); int integers[12]; ... ... some_func(cfunc); another_func(integers) ... ... some_func(function) another_func(array) int (*function)(); int *array; { { ... ... (*function)(10); i = array[10]; ... ... } } The name of the function "cfunc" becomes the address of the function in the same way that the name of the array "integers" becomes the address of the array. So why, when you use it, do you have to specify taking the contents of the variable "function", but not have to do the same with "array"? The parallel of these two uses of pointers seems strong. To get the address, you use the name. In the case of the array, the "[10]" indicates an indirection off of the primary expression, either in the case of "array[10]" or "integers[10]". But in the case of arrays, for some reason, if the primary expression is a function name, the "(10)" indicates "indirection" from the address, but if the primary expression is a variable name it does not. I'm curious what other people think about this. The current situation in which BOTH syntax 1 and 2 are allowed concurrently is certainly confusing and nonsensical. I would tend to support a change to syntax 2, with syntax 1 usage generating a warning, as the "=+" operators have done. It is possible this has been dealt with in the proposed C standard, which I have yet to see more than a summary of. If it is, what is the solution? While we're at it, where can people get a copy of The Real Thing? Ken Arnold