Xref: utzoo comp.bugs.4bsd:1658 comp.std.c:4160 Path: utzoo!utgpu!news-server.csri.toronto.edu!cs.utexas.edu!chinacat!sequoia!rpp386!jfh From: jfh@rpp386.cactus.org (John F Haugh II) Newsgroups: comp.bugs.4bsd,comp.std.c Subject: Re: Bug in users command Message-ID: <18981@rpp386.cactus.org> Date: 23 Jan 91 16:06:55 GMT References: <18965@rpp386.cactus.org> <24748:Jan2016:53:4291@kramden.acf.nyu.edu> <18969@rpp386.cactus.org> <6182:Jan2222:06:3991@kramden.acf.nyu.edu> Reply-To: jfh@rpp386.cactus.org (John F Haugh II) Organization: Lone Star Cafe and BBS Service Lines: 77 X-Clever-Slogan: Recycle or Die. In article <6182:Jan2222:06:3991@kramden.acf.nyu.edu> brnstnd@kramden.acf.nyu.edu (Dan Bernstein) writes: >For comp.std.c readers: This argument started when I said that the BSD >users.c appears to be incorrect. It passes a two-dimensional character >array to qsort(), but the comparison function was expecting just a >pointer to characters. John says that's correct. Repeat after me ... the type which qsort() expects is a (void *) (or in the older circles, (char *)). The comparision function should also be declared to accept two (void *)'s (or in the older circles, (char *)'s). This is all in the documentation. In the "Notes" section for my compiler - "The pointer to the base of the table should be of type pointer to element, and cast to pointer to character." This is the same vein as every other compiler in existence, and I believe (because my ANSI is not here right now) that ANSI C declares qsort() to have the following prototype (modulo a few "const"'s here and there) - void qsort (void *, unsigned, unsigned, int (*) (void *, void *)); That should make it pretty clear what type qsort() expects. >There is no array being passed. A *pointer* to the array is being >passed. According to the standard, a pointer to a character or a pointer to a void is being passed. There is no mechanism in the standard to create a pointer to an arbitrary object, or to find out the type of an object which has been passed to you. You are more than free to do int scmp (char (*a)[UT_NAMESIZE], char (*b)[UT_NAMESIZE]) { ... } but that most certainly is incorrect, according to the standard, since that function is not (int (*) (void *, void *)). The best you could do is int scmp (void *_a, void *_b) { char (*a)[UT_NAMESIZE] = _a; char (*b)[UT_NAMESIZE] = _b; ... } if that gives you some sense of moral superiority, but you are stuck doing strncmp ((char *) a, (char *) b, sizeof *a); by your logic in that case. How would qsort() create the parameters? You can't do (*compar) ((typeof base) (base + n)), ...) there simply is no mechanism to cast a pointer dynamically to some other type. How is qsort ever going to create the ((*c)[UT_NAMESIZE]) pointer? There is no type information regarding what "base" was on the other side of the function call. qsort doesn't know, doesn't care and can't find out. Finally, by the rule which says that (void *) and (char *) have the same representation, the BSD use of (char *) in place of (void *) is perfectly acceptable. Now are you happy? -- John F. Haugh II UUCP: ...!cs.utexas.edu!rpp386!jfh Ma Bell: (512) 832-8832 Domain: jfh@rpp386.cactus.org "13 of 17 valedictorians in Boston High Schools last spring were immigrants or children of immigrants" -- US News and World Report, May 15, 1990