[comp.lang.c] Frequently Asked Array Questions

junk1@cbnews.att.com (eric.a.olson) (03/30/91)

>Section 2. Arrays and Pointers
>
>20.  So what is meant by the "equivalence of pointers and arrays" in C?
>
>A:   An identifier of type array-of-T which appears in an expression
>     decays into a pointer to its first element; the type of the
>     resultant pointer is pointer-to-T.

    Exactly what kind of expression?
    Not, for instance, one where an lvalue is expected... now:

    I have been writing in C since '82 and thought that I had it down.
    Read K&R and K&R 2 religiously.   Became the person that others
    came to with C questions.    Followed Chris et al here as well.
    Today, I ran across a situation where a peer had:
	func()
	    {
		char array[7];
	    
	    if (array == 0)
		something;
	    }
    His code wasn't working.   I looked thru the rest of the code
    and suggested that he wanted 'array[0] == 0' rather than 'array == 0',
    and I furthermore charged that the compiler had warned him about
    this, and that he had ignored it.

    Well, it just ain't so.   No compiler we have complains about it.
    They complain about a test for equality with any other constant
    but 0, but even then, only that it is an illegal pointer/integer 
    combination.   (I understand that difference).

    It seems to me that a comparison between something of type
    auto array and something of type constant ought to at least produce
    a warning.  It's not like we're supposing even that it might be
    an extern and that the linker bound it to 0.

    I posed this to john ampe here at BL and he finally came up with this
    argument:
	the following is clearly legal:
	    {
		char x[7];
		char *p;
	    for (p=x+3; p != x; --p)
		something;
	    }
    therefore, testing an auto array name for equality to a constant
    is legal as well, since if you reduce the types you have the same
    types in both cases.   

    After looking at this, and the above excerpt from the FAQ, I had to
    concede that such a test was valid.  However,  I still feel a little
    strange about it.

    Can anyone here give another reason why this test is legal, or expound
    upon john's example?   Feel free to reply directly to:
					eao@mvucl.att.com

scs@adam.mit.edu (Steve Summit) (03/30/91)

In article <1991Mar30.060146.10515@cbnews.att.com> junk1@cbnews.att.com (eric.a.olson) writes:
>>20.  So what is meant by the "equivalence of pointers and arrays" in C?
>>
>>A:   An identifier of type array-of-T which appears in an expression
>>     decays into a pointer to its first element; the type of the
>>     resultant pointer is pointer-to-T.
>
>    Exactly what kind of expression?
>    Not, for instance, one where an lvalue is expected... now:

Actually, the quoted sentence from the FAQ list has a significant
error in it, and should instead read:

     An *lvalue* of type array-of-T which appears in an expression
     decays into a pointer to its first element...

This is The Rule, though it does have three exceptions, which are
not mentioned in the abridged FAQ list from which Eric quoted.
The exceptions, as described in the long list, are "when the
array is the operand of the sizeof() operator or of the &
operator, or is a literal string initializer for a character
array."  (The second exception is mildly equivalent to Eric's
"not where an lvalue is expected.")

>    Today, I ran across a situation where a peer had:
>		char array[7];
>	    if (array == 0)
>    No compiler we have complains about it.
>    They complain about a test for equality with any other constant
>    but 0, but even then, only that it is an illegal pointer/integer 
>    combination.   (I understand that difference).

The conditional expression

	if (array == 0)

does not match any of the three exceptions, so the compiler
dutifully generates a pointer to the first element of the array,
and then compares it to the null pointer, which is, as Eric
correctly observes, guaranteed not to succeed.  When exposed to
the light of day like this, this behavior does seem odd, but the
compiler is just blindly following the rules, as compilers are
wont to do.

A legitimate message from the compiler in this case would be
"warning: constant in conditional context."  (A more interesting
message might be "warning: comparison of constants.")  Standard
lint, however, does not make this diagnosis, presumably because
it does not treat array names as the constants they really are.
(In this case, the array name is only quasi-constant, because its
storage class is auto.  However, lint doesn't complain about
comparisons of statically-allocated array names, either.)

I've added this case to my lint wish list.


>	the following is clearly legal:
>	    {
>		char x[7];
>		char *p;
>	    for (p=x+3; p != x; --p)
>		something;
>	    }
>    therefore, testing an auto array name for equality to a constant
>    is legal as well, since if you reduce the types you have the same
>    types in both cases.   

Actually, this example is slightly different.  The types are the
same, but it is not "testing an auto array name for equality to a
constant," since p is a variable.

                                            Steve Summit
                                            scs@adam.mit.edu

manning@nntp-server.caltech.edu (Evan Marshall Manning) (03/31/91)

scs@adam.mit.edu (Steve Summit) writes:

>>    Today, I ran across a situation where a peer had:
>>		char array[7];
>>	    if (array == 0)
>>    No compiler we have complains about it.
>>    They complain about a test for equality with any other constant
>>    but 0, but even then, only that it is an illegal pointer/integer 
>>    combination.   (I understand that difference).

>The conditional expression

>	if (array == 0)

>does not match any of the three exceptions, so the compiler
>dutifully generates a pointer to the first element of the array,
>and then compares it to the null pointer, which is, as Eric
>correctly observes, guaranteed not to succeed.  When exposed to
>the light of day like this, this behavior does seem odd, but the
>compiler is just blindly following the rules, as compilers are
>wont to do.

>A legitimate message from the compiler in this case would be
>"warning: constant in conditional context."  (A more interesting
>message might be "warning: comparison of constants.")  Standard
>lint, however, does not make this diagnosis, presumably because
>it does not treat array names as the constants they really are.
>(In this case, the array name is only quasi-constant, because its
>storage class is auto.  However, lint doesn't complain about
>comparisons of statically-allocated array names, either.)

>I've added this case to my lint wish list.

PC-Lint from Gimpel (and presumably Flexi-Lint from the same source)
Has this to say:
                 _
        if (p == 0)
temp2.c  6  Warning 506: Constant value Boolean

Again, I highly recommend this product.

***************************************************************************
Your eyes are weary from staring at the CRT for so | Evan M. Manning
long.  You feel sleepy.  Notice how restful it is  |      is
to watch the cursor blink.  Close your eyes.  The  |manning@gap.cco.caltech.edu
opinions stated above are yours.  You cannot       | manning@mars.jpl.nasa.gov
imagine why you ever felt otherwise.               | gleeper@tybalt.caltech.edu
i=3;do{putchar(((0x18|1<<!(i&2)|(!!i==i)*2)<<2|2>>i%2)^(2<<1+i));}while(i--);