Bug in users command

Dan Bernstein brnstnd at kramden.acf.nyu.edu
Wed Jan 23 09:06:39 AEST 1991


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.

In article <18969 at rpp386.cactus.org> jfh at rpp386.cactus.org (John F Haugh II) writes:
> [ I'm redirecting this to the ANSI-C group because it seems that Dan has
>   some misunderstanding about what the current standards say about passing
>   arrays and their addresses. ]

Really? Then why can't you point out my mistake?

Suppose you have the following:

  foo(s) char *s; { ... }
  char c[300][500];
  foo(&(c[17]));

Is this correct?

I see it this way. c is an array of array of char. c[17] is an array of
char. &(c[17]) is a pointer to an array of char. foo does not expect a
pointer to an array of char; it expects a pointer to char.

We all know that the value of an array is the value of a pointer to the
first element of an array. But that doesn't apply here.

Is there a conversion that says ``a pointer to c[17] is a pointer to
c[17][0]''? I don't see any justification for that in K&R. I certainly
wouldn't use such a coding style, and I hope Saber-C and other program
checkers complain about it.

Now John is right that this code will work on most real machines---pcc
will even throw away the & in &(c[17]) and complain about it. But
suppose you have a machine where pointers to characters are stored as
byte addresses, while all larger pointers are aligned on word boundaries
and then divided by 4 internally. Then &(c[17]) will be a factor of 4
different from &(c[17][0]), and the code will fail miserably.

> In article <24748:Jan2016:53:4291 at kramden.acf.nyu.edu> brnstnd at kramden.acf.nyu.edu (Dan Bernstein) writes:
> >> How does a pointer to an unknown number of characters differ from a
> >> pointer to a known number of characters when passed as an argument?
> >It doesn't. It does, however, differ from a pointer to an *array* of
> >characters.
> How?  When an array of any size, known or unknown, is passed as an
> argument to a function,

There is no array being passed. A *pointer* to the array is being
passed.

> The address of an array, that is,
> the address of each member of "char names[MAXUSERS][UT_NAMESIZE]"
> where each member is an "array[UT_NAMESIZE] of type char", is the
> address of the first member of that array.

We're talking about C pointers, not their most common implementation.

> >scmp() does not get passed a char [UT_NAMESIZE]. It gets passed a
> >pointer to a char [UT_NAMESIZE]. You claim there is an equivalence
> >between pointer to array of char and pointer to char? You claim it's
> >spelled out in K&R? I don't believe you.
> It gets passed the address of the first character in the
> "array[UT_NAMESIZE] of type char".  K&R is explicit on this point.

Where?

> A "pointer to a char [UT_NAMESIZE]" is a pointer to a char with
> the value of the 0th element in the array.  This is why "&x[0]"
> is identical to an unadorned "x" for all types of "x" and all sizes
> of the array of "x"'s.

No. Your second sentence is correct, but it is not logically connected
to the previous sentence.

---Dan



More information about the Comp.bugs.4bsd.ucb-fixes mailing list