From: torek@horse.ee.lbl.gov (Chris Torek)
Newsgroups: comp.lang.c
Subject: Re: sscanf? What am I doing wrong?
Date: 7 Sep 1992 19:12:43 GMT
Organization: Lawrence Berkeley Laboratory, Berkeley
Reply-To: torek@horse.ee.lbl.gov (Chris Torek)
NNTP-Posting-Host: 128.3.112.15

[given]
>>  char partA[20];
>>  char tran[] = "transmit";
>>  if (partA==tran) ...

In article <1992Sep3.134259.14601@microware.com> adam@microware.com
(Adam Goldberg) writes:
>partA and tran are both POINTERS to some number of characters.

Well, no.  The variables `partA' and `tran' are each arrays,
specifically, `array 20 of char' and `array 9 of char' respectively.

>The if statement (partA == tran) is checking if the POINTERS are equal...

This, however, is correct, by The Rule:

    In a value context, an object of type `array N of T' is converted
    to a value of type `pointer to T' by locating the first element of
    that array, i.e., the one with subscript 0.

In this case, both partA and tran are in value contexts, both are
objects of type `array N of char' (their N's differ, but N is dropped
along the way so this does not matter), and so both become values of
type `pointer to char', namely &partA[0] and &tran[0] respectively.

>clearly they're not, unless you did something previously like
>partA = tran.

Since partA is an array, which is not (per ANSI C terminology) a
`modifiable lvalue', such an assignment is illegal.  In any case, the
programmer may not alter the address of an object---the address of each
object is a matter for the compiler and/or machine to arrange, and the
programmer has no say in this.  (Aside, that is, from machine-dependent
tricks like mixing C and assembly.)  The C language further guarantees
that for any two different objects X and Y of the same type, &X != &Y.
This means that we can be certain that partA != tran, and that the
code inside the `if' will *never* run.

(There are even stronger guarantees when you start casting to
common superset pointer types such as `void *', but then the rules
get complicated since (void *)&foo.x can be equal to (void *)&foo.y,
and so forth.)

>What you (probably) want to do is something like this:
>   if(strcmp(partA, tran)==0)

Right.  Alternatively, one can make one (or both) of the variables
`char *' and then set one or both to the same pointer value, so that
they compare equal.

If you want to understand C expressions, you must learn three basic
elements:

    - objects versus values (or `lvalues' vs `rvalues');
    - the type system;
    - the rules for converting objects to values, and for making
      values compatible.

(Some people lump all of these together under `the type system', but I
prefer to separate them.)  Once you have these down, you should be able
to determine the `object'- or `value'-ness of any expression, along
with its type.  If you can then find the value, you can predict exactly
what that expression means, or know that it is impossible to say (e.g.,
if the value is `uninitialized' or garbage').

And then you are reading to start on side effects. :-)
-- 
In-Real-Life: Chris Torek, Lawrence Berkeley Lab CSE/EE (+1 510 486 5427)
Berkeley, CA		Domain:	torek@ee.lbl.gov
Newsgroups: comp.lang.c