[comp.lang.c] Pointer incrementation and assignment

abcscagz@csuna.csun.edu (Jeff Boeing) (05/26/89)

This has bugged me for quite some time....

     int *a;

Say you implement this on a machine that uses byte addressing (memory location
4000 contains 1 byte, memory location 4001 contains 1 byte, and so on), and
this particular C compiler, quite justifyably, interprets an "int" to be a
signed two-byte value.  Now, by definition, when you do this:

      a++;

You increment the actual address stored in a by TWO, not just by one.
Furthermore, if the compiler allows it, this is also perfectly legal:

      a = 4000;

This sets a to point to memory location 4000.  A subsequent a++ would increase
a to 4002.  But would doing this:

      a += 1;

increase a by 1 or by 2?  Or how about

      a = a + 1;

??  Inquiring minds want to know!

-- 
Jeff Boeing:  ...!csun.edu!csuna!abcscagz    (formerly tracer@stb.UUCP)
----------------------------------------------------------------------------
"Let's split up -- we can do more damage that way."
                       -- Gh0stbusters

giguere@aries5.uucp (Eric Giguere) (05/26/89)

In article <2015@csuna.csun.edu> abcscagz@csuna.csun.edu (Jeff Boeing) writes:
>Furthermore, if the compiler allows it, this is also perfectly legal:
>
>      a = 4000;
>
>This sets a to point to memory location 4000.  A subsequent a++ would increase
>a to 4002.  But would doing this:
>
>      a += 1;
>
>increase a by 1 or by 2?  Or how about
>
>      a = a + 1;

Both cases yield the same result as a++ so that a is now 4002 and not 4001.
In C it's implicit that any integer added to a pointer is first multiplied
by the size of the pointer's base type... I don't have the Standard in front
of me, but to quote K&R 2 on page 205:

   "A pointer to an object in an array and a value of any integral type
    may be added.  The latter is converted to an address offset by
    multiplying it by the size of the object to which the pointer points. 
    The sum is a pointer of the same type as the original pointer ...."

This feature can be useful when dealing with non-trivial types, such as
arrays of structures.  One of my favorite ways to display several lines
of static text is to use something of the form:

    static char *MyText[] =
      {
        "Usage:  blart [-r] problem\n",
        "    blart is a generic program suitable for general-purpose",
        "    problem solving and is often described in the literature.\n",
        "    Arguments:\n",
        "        -r       solve some problem at random",
        "        problem  a specific problem to be solved\n",
        "    See also `foo'.",
        NULL
      };

    Usage()
      {
        char **text;

        for( text = MyText; *text != NULL; ++text )
            puts( *text );
      }

Here I specifically depend upon the fact that `++text' adds   

     sizeof( char * )

to the current value of `text' to get me the next element in the array...

Eric Giguere                                  268 Phillip St #CL-46
For the curious: it's French ("jee-gair")     Waterloo, Ontario  N2L 6G9
Bitnet  : GIGUERE at WATCSG                   (519) 746-6565
Internet: giguere@aries5.UWaterloo.ca         "Nothing but urges from HELL!!"

henry@utzoo.uucp (Henry Spencer) (05/26/89)

"a++", "a += 1", and "a = a + 1" are all precisely synonymous, by definition,
excluding obscure side effects.  When "a" is a pointer, all three increment
it to point to the next object of the type it points to.  This typically
means adding sizeof(*a) to "a", treating it as if it were an integer.  Note
the word "typically" in that sentence -- it doesn't have to work that way.
Note also that there may not *be* a "next object" unless "a" and "a+1" both
point into the same array (or one past its end).
-- 
Van Allen, adj: pertaining to  |     Henry Spencer at U of Toronto Zoology
deadly hazards to spaceflight. | uunet!attcan!utzoo!henry henry@zoo.toronto.edu

guy@auspex.auspex.com (Guy Harris) (05/27/89)

>But would doing this:
>
>      a += 1;
>
>increase a by 1 or by 2?

It would increment the value of the variable "a" by 1, just as would
"a++".  That is, it would cause "a" to point to an element one further
along in the (putative) array into which it points.  In other words, on
your example machine, it would increment the address stored in the
variable "a" by 2.

>Or how about
>
>      a = a + 1;

Same thing.

"a++", "a += 1", and "a = a + 1" all add 1 to the value of "a",
regardless of the type of "a"; it's just that the meaning of "add 1 to
the value of 'a'" differs depending on the type of "a".

If "a" is of integral type, its value plus 1 is the successor to the
integer that is its value (modulo - no pun intended - overflow or
modular-arithmetic wraparound for unsigned types). 

If "a" is of floating-point type, its value plus 1 is the sum of its
current value and 1.0, given the implementation of floating-point
arithmetic on your machine (taking into account overflow, loss of
significance of the "1.0" - i.e., 1.0e36 + 1.0 probably isn't
1.000......01e36 unless you have lots of bits of precision).

If "a" is of pointer type, its value plus 1 is a pointer to the element
following the one pointed to by "a" in the (putative) array to which the
element pointed to by "a" belongs.  (If the value of "a" is represented
by the number N - i.e., "a" points to something starting at the Nth
byte, 0-origin of course, in your address space - the value of "a+1" is
represented by the number N+sizeof (*a).  Be careful *not* to just think
of this as "adding 'sizeof(*a)' to 'a'.")

Think of it in those terms, rather than, say, thinking of "a++" as
shorthand for "part of how you get at your machine's autoincrement
address mode", and it becomes clearer (*and* more machine-independent -
not all machines *have* an autoincrement addressing mode, for instance).