<<< Date Index >>>     <<< Thread Index >>>

Re: Little code cleanup



On Fri, Mar 07, 2008 at 03:28:08PM +0100, Vincent Lefevre wrote:
> On 2008-03-06 10:08:34 +0000, Nicolas Bernard wrote:
> > You are missing my point. They EVALUATE to pointers, but they are
> > not pointers.
> 
> No, the point is that the test is performed on the pointer itself.
> If you think that the test array == NULL is wrong, then for the same

The test isn't wrong, it's just not particularly useful, and
slightly inefficient.  The warning from gcc rightly points this out.

> > By "it doesn't make sense", it was not implied that the code was
> > wrong, only that it is unneeded
> 
> Not much less unneeded than assertion checking and debug messages.

Quite true; in this case, none of the above are necessary or useful,
since the test is being applied to a constant pointer which is
guaranteed to be non-NULL.  In the general case, all are useful.  In
this specific case, they are all not useful.

Let's take another quick look at the C standard:

They are arrays, but in expressions, they evaluate to pointers
(with a few exceptions). More precisely:
 
[ISO C99, 6.3.2.1]
       [#3] Except when it is the operand of the sizeof operator or
       the  unary  &  operator,  or  is  a  string  literal used to
       initialize an array, an expression that has type ``array  of
       type''  is converted to an expression with type ``pointer to
       type'' that points to  the  initial  element  of  the  array
       object  and  is  not  an  lvalue.   If  the array object has
       register storage class, the behavior is undefined.

There are a couple of extremely important things to note here.  The
first one is the phrase "is converted" -- for the term "converted" to
be applicable, it means that one thing is being changed to a second
thing, which is different and distinct from the first thing.  If the
two things are already the same, then conversion is impossible and an
incorrect terminology.  The second thing to note is the phrase "and is
not an lvalue."  Here, we mean that the pointer can not be reassigned;
i.e. it is a constant.  This normally is not true of generic pointers.

It should be clear that an array is NOT simply a pointer.  They are
different from pointers in the generic case in the following ways:

  - they can not be lvalues
  - they are constant
  - they typically may only point to memory allocated in specific
    regions of memory (e.g. the BSS, as opposed to the stack or heap),
    whereas pointers may point anywhere [this may be dependent upon
    implementation]
  - they can not ever be NULL

While the name of an array is converted to a pointer type, and is
equivalent to a pointer type in most cases, it is not, strictly
speaking, the same as a pointer.  And thus not all operations which
one can do to a pointer make sense in the same way as they would for a
pointer, when applied to an array.  This case is such a case.

> > and resulting of a confusion between an array and a pointer.
> 
> There is no confusion. The code could also have been obtained by
> a copy-paste where the test was needed before. 

...which sounds an awful lot to me like the programmer was confused.

> And there is nothing wrong with this test.

That's not quite true; the thing which is wrong with it is that it
needlessly produces a compiler warning which is not interesting or
necessary for this case.  Again, in the general case the test is fine;
but in this specific case it is useless and produces noise in the form
of compiler warnings, which can easily be eliminated by rewriting the
check.  Thus it is undesirable.
 
> You're wrong. 

Making such bald-faced, confrontational statements is inflamatory and
rude.  And in this case, it happens to be untrue as well.

> There are cases where the test is really necessary (in

And this is not such a case.

> So, the warning is useless and bad.

The warning is only useless in this case, because the check is
pointless.  The warning itself is perfectly legitimate.

> array and &array do not evaluate to the same pointer.
> array is transformed into &array[0].

That statement is trivially proven to be incorrect with a tiny little
C program:

$ cat ptr.c
#include <stdio.h>
int main(int argc, char **argv) {
        char name[] = "foo";
        printf("value of name = %0x\n", name);
        printf("value of &name = %0x\n", &name);
        printf("value of &name[0] = %0x\n", &name[0]);
        return 0;
}

$ ./ptr
value of name = bfe50f60
value of &name = bfe50f60
value of &name[0] = bfe50f60

They do indeed evaluate to the same pointer, always.  I didn't feel
like writing the malloc code to also check dynamically allocated
strings, but I'm pretty certain the same is true for those as well.
The only thing I can think of which I'm not sure if it might be
different is arrays of structs...  I have a vague notion that they may
store metadata about the organization of the structure before the
first element of the array; but that might be an
implementation-specific detail, or I might just be on crack... ;-)


-- 
Derek D. Martin    http://www.pizzashack.org/   GPG Key ID: 0xDFBEAD02
-=-=-=-=-
This message is posted from an invalid address.  Replying to it will result in
undeliverable mail due to spam prevention.  Sorry for the inconvenience.

Attachment: pgpKIjVbrOeoV.pgp
Description: PGP signature