[comp.lang.c] When is a cast not a cast?

bph@buengc.BU.EDU (Blair P. Houghton) (05/02/89)

Here's one that popped up last night/this morning (keep that Sanka
away from me! %-S )

I wanted to be a 'good little programmer' and make all the types
match up, so I was using casts wherever a promotion might be
non-obvious.  In particular, I fell for:  (the line numbers are shown
only for reference)

1   main()
2   {
3	char *c;
4	char *p;
5	int i;
6	...
7	c = "somestring";  /* Nothing fancy, null-terminated. */
8	i = 4;  /* For example. */
9	...
10 	p = (c + (char *) i);  /* More trouble than it's worth... */
11	...
12  }

wherupon both the lint(1) and cc(1) in my Ultrix 2.2 piped-up with
warnings that the 'operands of + have incompatible types' on line 10...

Now, who is having the more serious problem with (reduntantly?) casting
i to be a char * before this addition: me, or the programmming tools
under Ultrix version 2.2?

How can two things explicitly identifiable as being the same type
(one by declaration, the other by that all-powerful fiat, the cast)
be suddenly 'incompatible'?

I have an inkling as to what I'm missing, but it makes little sense
regardless:  It involves getting the integer quantity (i * sizeof(char *))
which leaves one right back in the pigpen wondering how to cast this greater
integer as in 

	p = (c + (char *)( i * sizeof(char *) );

I get the feeling that one isn't allowed pointer arithmetic at all.
It only seems to allow such things as " &(foo[bar]) - foo ", where it
is 100% certain that both operands point to the same data segment.

Additional info:
 - lexical order of c and (char *)i on line 10 above is immaterial;
 - the extra parentheses are immaterial;
 - initialization method is immaterial;
 - declaring c as '(3)  char c[];' changes nothing;
 - declaring i as '(5)  char *i;' then setting '(8)  i = (char *) 4;' convinces
     lint to say:
      'foo.c(10): warning: illegal combination of pointer and integer, op ='
     as well as the same-old-same-old about 'incompatible types';
 - I haven't checked it on other compilers.

				--Blair
				  "Goodness!  A conundrum. `,:-q"

krazy@claris.com (Jeff Erickson) (05/02/89)

From article <2747@buengc.BU.EDU>, by bph@buengc.BU.EDU (Blair P. Houghton):
> 1   main()
> 2   {
> 3	char *c;
> 4	char *p;
> 5	int i;
> 6	...
> 7	c = "somestring";  /* Nothing fancy, null-terminated. */
> 8	i = 4;  /* For example. */
> 9	...
> 10 	p = (c + (char *) i);  /* More trouble than it's worth... */
> 11	...
> 12  }
> 
> wherupon both the lint(1) and cc(1) in my Ultrix 2.2 piped-up with
> warnings that the 'operands of + have incompatible types' on line 10...

Well, first of all, the only arithmetic operations allowed on pointers
are pointer+integer, integer+pointer, pointer-integer, and pointer-pointer.
Pointer+pointer is illegal, and therefore, "operands of + have incompatible
types".

Secondly, I believe what you *want* on line 10 is

				p = c + i;

This is equivalent to "p = &(c[i]);".  It sets p equal to a pointer to the 
i'th char after c.


-- 
Jeff Erickson       Claris Corporation  | Birdie, birdie, in the sky,
408/987-7309      Applelink: Erickson4  |   Why'd you do that in my eye?
krazy@claris.com     ames!claris!krazy  | I won't fret, and I won't cry.
       "I'm a heppy, heppy ket!"        |   I'm just glad that cows don't fly.

davidsen@steinmetz.ge.com (Wm. E. Davidsen Jr) (05/02/89)

In article <2747@buengc.BU.EDU> bph@buengc.bu.edu (Blair P. Houghton) writes:

| I wanted to be a 'good little programmer' and make all the types
| match up, so I was using casts wherever a promotion might be
| non-obvious.  In particular, I fell for:  (the line numbers are shown
| only for reference)
| 
| 1   main()
| 2   {
| 3	char *c;
| 4	char *p;
| 5	int i;
| 6	...
| 7	c = "somestring";  /* Nothing fancy, null-terminated. */
| 8	i = 4;  /* For example. */
| 9	...
| 10 	p = (c + (char *) i);  /* More trouble than it's worth... */
| 11	...
| 12  }
| 
| wherupon both the lint(1) and cc(1) in my Ultrix 2.2 piped-up with
| warnings that the 'operands of + have incompatible types' on line 10...

  C allows expressions involving a pointer and an int. The expression
	ptr + int
has the same type as ptr, and the address "ptr plus (int times the size
of the base type of ptr). The following expressions refer to the same
location, using the declarations at the start of the example:
	/* declare */
	int *ptr;	/* this is our pointer */
	int m;		/* this is the int we add */
	int *value;	/* this holds the resulting address */

	/* these result in the same value */
	value = (ptr + m);	/* parens optional */
	value = &ptr[m];
	value = &m[ptr];	/* ugly and confusing, but legal */

  In addition to the result of adding (or subtracting) an int and
pointer, the result of subtracting two pointers is an int, the number of
items of the base type of the pointers, subject to the following:
	a) the pointers must be of the same type
	b) the pointers must be into the same data structure
	   or the results will not be portable (and may not
	   work at all in some implementations).

  For example:
	int p[20], *ptr1, *ptr2, value;

	ptr1 = &p[0];
	ptr2 = &p[4];
	value = ptr2 - ptr1;	/* always 4 */

  regardless of the sizeof(int), the resul;t is four, because it is the
*number of items* of the base type between the pointers. Changing the
'int' type to any other type, including struct and union types, will not
effect the value of the subtraction. This eliminates some of the address
arithmetic tricks required by older languages.

  The reason that you are getting errors is that you are trying to add
two pointers, which is not a defined operation. Looking at your original
code again,

| 10 	p = (c + (char *) i);  /* More trouble than it's worth... */

what you want is just
	p = c + i;		/* no trouble at all */

Hope I made this clear, it's harder to understand once you learn it
wrong... I'm sure the usual people who respond to every question will
reply to this one.
-- 
	bill davidsen		(wedu@crd.GE.COM)
  {uunet | philabs}!steinmetz!crdos1!davidsen
"Stupidity, like virtue, is its own reward" -me

rkl@cbnewsh.ATT.COM (kevin.laux) (05/02/89)

In article <2747@buengc.BU.EDU>, bph@buengc.BU.EDU (Blair P. Houghton) writes:
| Here's one that popped up last night/this morning (keep that Sanka
| away from me! %-S )
| 
| I wanted to be a 'good little programmer' and make all the types
| match up, so I was using casts wherever a promotion might be
| non-obvious.  In particular, I fell for:  (the line numbers are shown
| only for reference)
| 
| 1   main()
| 2   {
| 3	char *c;
| 4	char *p;
| 5	int i;
| 6	...
| 7	c = "somestring";  /* Nothing fancy, null-terminated. */
| 8	i = 4;  /* For example. */
| 9	...
| 10 	p = (c + (char *) i);  /* More trouble than it's worth... */
| 11	...
| 12  }
| 
| wherupon both the lint(1) and cc(1) in my Ultrix 2.2 piped-up with
| warnings that the 'operands of + have incompatible types' on line 10...
| 
| Now, who is having the more serious problem with (reduntantly?) casting
| i to be a char * before this addition: me, or the programmming tools
| under Ultrix version 2.2?

	[ stuff deleted ]

	But you want p to point into the string by an offset i.

	Line 10 should simply be

		p	= c + i;

	so that the value of pointer c is incremented by the value of integer i
times the sizeof a char.

	You don't want to add two *pointers* together and place the result in
p.  Think about the result from subtacting two pointers:

	char	c [8];
	char	*p;
	int	i;

	p	= &c [7];
	i	= p - c;

	The result of p - c is 8, an integer.

--rkl

gwyn@smoke.BRL.MIL (Doug Gwyn) (05/02/89)

In article <2747@buengc.BU.EDU> bph@buengc.bu.edu (Blair P. Houghton) writes:
>10 	p = (c + (char *) i);  /* More trouble than it's worth... */

Addition of pointers is a meaningless operation.

ark@alice.UUCP (Andrew Koenig) (05/02/89)

In article <2747@buengc.BU.EDU>, bph@buengc.BU.EDU (Blair P. Houghton) writes:

> 3	char *c;
> 4	char *p;
> 5	int i;
> 6	...
> 7	c = "somestring";  /* Nothing fancy, null-terminated. */
> 8	i = 4;  /* For example. */

> 10 	p = (c + (char *) i);  /* More trouble than it's worth... */

> wherupon both the lint(1) and cc(1) in my Ultrix 2.2 piped-up with
> warnings that the 'operands of + have incompatible types' on line 10...

Correct.  You cannot add two pointers -- you can only add
a pointer and an integer.

You can SUBTRACT two pointers (to the same type); the result
of that is an integer, not a pointer.

If p is a pointer to element n of some array, then p+i is a
pointer to element n+i of that array.

If p isn't a pointer to an array element, you're on your own.
[C-T&P, p. 29]
-- 
				--Andrew Koenig
				  ark@europa.att.com

suitti@haddock.ima.isc.com (Stephen Uitti) (05/03/89)

In article <2747@buengc.BU.EDU> bph@buengc.bu.edu (Blair P. Houghton) writes:
>I wanted to make all the types match up, so I was using casts
>wherever a promotion might be non-obvious.  In particular, I fell for:
>3	char *c;
>5	int i;
>7	c = "somestring";  /* Nothing fancy, null-terminated. */
>8	i = 4;  /* For example. */
>10 	p = (c + (char *) i);  /* More trouble than it's worth... */
>wherupon cc(1) said that the 'operands of + have incompatible types'
>
>Now, who is having the more serious problem with (reduntantly?) casting
>i to be a char * before this addition: me, or the programmming tools
>under Ultrix version 2.2?

It isn't even redundant.  It means the wrong thing.  Casts tend not
to be redundant.  Sometimes they are used for "portability".  Not here.

A better example is
	p = "foobar" + "barfoo";	/* what does this mean? */
The line
	p = c + i;	/* means p = c[i] or p = i[c] or p = i + c */
does something useful.

K&R says something about what arithmetic can be done with pointers.
I'd quote from the bible were it required.

Stephen.

richard@aiai.ed.ac.uk (Richard Tobin) (05/03/89)

>Addition of pointers is a meaningless operation.

Not always.  (I'm not discussing whether it's legal in C, just whether it's
meaningless.)

This is perfectly reasonable:

  char *p, *q, *r, *s;

   ...

  for(...)
  {
       ...
       s = p + (q - r);
       ...
  }

(assuming they point into the same array).

Now suppose p and q are constant in the loop, but r isn't.  Then you
might want to do:

  t = p + q;

  for(...)
  {
       ...
       s = t - r;
       ...
  }

Of course, there's no reasonable declaration for t, so you'd probably
have to use some casts and treat them as integers (no flames please;
for some people writing some programs sometimes portability to some
machines isn't important).

A good compiler might do this for you.

-- Richard
-- 
Richard Tobin,                         JANET: R.Tobin@uk.ac.ed             
AI Applications Institute,             ARPA:  R.Tobin%uk.ac.ed@nss.cs.ucl.ac.uk
Edinburgh University.                  UUCP:  ...!ukc!ed.ac.uk!R.Tobin

schaefer@ogccse.ogc.edu (Barton E. Schaefer) (05/03/89)

In article <2747@buengc.BU.EDU> bph@buengc.bu.edu (Blair P. Houghton) writes:
} Here's one that popped up last night/this morning (keep that Sanka
} away from me! %-S )

I think you've definitely had too much of it. :-)

} I wanted to be a 'good little programmer' and make all the types
} match up, so I was using casts wherever a promotion might be
} non-obvious.  In particular, I fell for:
} 
} 3	char *c;
} 4	char *p;
} 5	int i;
} 10 	p = (c + (char *) i);  /* More trouble than it's worth... */
} 
} wherupon both the lint(1) and cc(1) in my Ultrix 2.2 piped-up with
} warnings that the 'operands of + have incompatible types' on line 10...
} 
} How can two things explicitly identifiable as being the same type
} (one by declaration, the other by that all-powerful fiat, the cast)
} be suddenly 'incompatible'?

That's because of the way pointer arithmetic is defined:

	pointer op integer yields pointer, where op is plus or minus
	pointer minus pointer yields integer

See K&R I, p. 99, the last paragraph above section 5.5.  Subtraction is
the only operation allowed on two pointers.

} Now, who is having the more serious problem with (reduntantly?) casting
} i to be a char * before this addition: me, or the programmming tools
} under Ultrix version 2.2?

It's you, because the cast is neither redundant nor correct.

} I have an inkling as to what I'm missing, but it makes little sense
} regardless:  It involves getting the integer quantity (i * sizeof(char *))

Actually, it would be sizeof(char) that you are interested in.  But you
are confused about how it gets involved in the computation.

} which leaves one right back in the pigpen wondering how to cast this greater
} integer as in 
} 
} 	p = (c + (char *)( i * sizeof(char *) );

When you write

	p = c + i;

for any pointers p and c of the same type and any integer i, then i is
automatically scaled by sizeof *c (e.g., if float *c, then sizeof(float)),
so that the result of the pointer arithmetic is a pointer to a location
i * sizeof(float) bytes after c.  If we take

	float *p, *c;

as an example, the "equivalent" operation is

	p = (float *) ((int)c + i * sizeof(float));

I put "equivalent" in quotes because because the (int)c cast is not well-
defined in general, so the compiler will not usually implement pointer
arithmetic in this way.  It just happens to work on certain widely
available machines with a linear address space and 32-bit pointers. :-)
-- 
Bart Schaefer       "And if you believe that, you'll believe anything."
							-- DangerMouse
CSNET / Internet                schaefer@cse.ogc.edu
UUCP                            ...{sun,tektronix,verdix}!ogccse!schaefer

bph@buengc.BU.EDU (Blair P. Houghton) (05/04/89)

In article <10191@smoke.BRL.MIL> gwyn@brl.arpa (Doug Gwyn) writes:
>In article <2747@buengc.BU.EDU> bph@buengc.bu.edu (Blair P. Houghton) writes:
>>10 	p = (c + (char *) i);  /* More trouble than it's worth... */
>
>Addition of pointers is a meaningless operation.

Philosophically, it's rubbish.  According to the language def., it's pure
science.

Apparently, in C, one can not only add apples to oranges and get more
oranges, one can add nothing but apples to the oranges, not even oranges
themselves.

Now, I don't mind being told by the compiler that I'm screwing up by
subtracting pointers that may point to different data spaces (even though
it is my belief that such a subtraction should occur vectorially, and
generate the proper memory offset to get me from ram-byte A to ram-byte B,
going through data/text/etc pages as necessary...) but I find it more than
unsettling that a pointer offset can not be expressed and manipulated
directly in the pointer type.  At least, not without first multiplying or
dividing by the proper sizeof(*type).

				--Blair
				  "A little older,
				   marginally wiser..."

rwhite@nusdhub.UUCP (Robert C. White Jr.) (05/04/89)

in article <2747@buengc.BU.EDU>, bph@buengc.BU.EDU (Blair P. Houghton) says:
[p and c are of type (char *)]
> 10 	p = (c + (char *) i);  /* More trouble than it's worth... */

and totally inaccurate too boot.  The + operator is defined separately for
the addition of a pointer-to-type and and interger.  The specs indicate
that you will get the operation p=c+(i*sizeof_typeof_c) so the cast is
in error.  pointer + interger is legal.  if you had an array of structures
anmed "strarray" and you set a pointer to the Nth entry, and you wanted
to get to the N+Mth entry the following code is legal and correct:

structure somestruct strarry[1000], *ptr;
ptr = strarry[N];
...
ptr = ptr + M; /* or ptr += M */
...


[Unless, of course, I am brain dammaged and therefore not correct in
interpreting this stuff]

Rob.

gwyn@smoke.BRL.MIL (Doug Gwyn) (05/04/89)

In article <2759@buengc.BU.EDU> bph@buengc.bu.edu (Blair P. Houghton) writes:
-In article <10191@smoke.BRL.MIL> gwyn@brl.arpa (Doug Gwyn) writes:
->In article <2747@buengc.BU.EDU> bph@buengc.bu.edu (Blair P. Houghton) writes:
->>10 	p = (c + (char *) i);  /* More trouble than it's worth... */
->Addition of pointers is a meaningless operation.
-Philosophically, it's rubbish.  According to the language def., it's pure
-science.

No, it's rubbish in any case.

-... but I find it more than
-unsettling that a pointer offset can not be expressed and manipulated
-directly in the pointer type.  At least, not without first multiplying or
-dividing by the proper sizeof(*type).

You're making things much harder than they really are.

	p = c + i;

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

>Now, I don't mind being told by the compiler that I'm screwing up by
>subtracting pointers that may point to different data spaces (even though
>it is my belief that such a subtraction should occur vectorially, and
>generate the proper memory offset to get me from ram-byte A to ram-byte B,
>going through data/text/etc pages as necessary...)

Uhh, offset in *what units*?  Pointer subtraction doesn't tell you how
many "char"s there are between the pointed-to objects, it tells you how
many objects *of the storage type that the pointers both point to* (if
they point to different types, you can't subtract them) are between them
(well, that plus one - "&foo[0]" and "&foo[1]" have nothing between
them, or between them and their Calvin Klein's for that matter, but
"&foo[1] - &foo[0]" is 1), under the assumption that they both point to
members of an array of objects of that type. 

>but I find it more than unsettling that a pointer offset can not be
>expressed and manipulated directly in the pointer type.

Why?  "pointer offsets", if by that you mean "the value of one pointer
relative to another", aren't the same sorts of objects as pointers.

mat@mole-end.UUCP (Mark A Terribile) (05/04/89)

> I wanted to be a 'good little programmer' and make all the types
> match up, so I was using casts wherever a promotion might be
> non-obvious.  ...

(Enter flame mode.)
AAAaaaarrrgggghhh!  This is not FORTRAN II.  Mixed mode is supported!  If you
are going to scatter the code with casts, we might as well go back to assembler
so that you can write the conversion instructions ...  For portability, we can
use MIX-MASTER.
(Exit flame mode.)

> 3	char *c;
> 5	int i;
> 10 	p = (c + (char *) i);  /* More trouble than it's worth... */
 
> wherupon both the lint(1) and cc(1) in my Ultrix 2.2 piped-up with
> warnings that the 'operands of + have incompatible types' on line 10...

They sure do.
 
> How can two things explicitly identifiable as being the same type
> (one by declaration, the other by that all-powerful fiat, the cast)
> be suddenly 'incompatible'?

To take the example of FORTRAN (an example which is probably brain-damaged
and which MIGHT have been fixed in -77), you cannot write

	LOGICAL FLAG1, FLAG2

		. . .

	IF( FLAG1 .EQ. FLAG2 ) . . .
 

> I have an inkling as to what I'm missing, ... It involves getting the integer
> quantity (i * sizeof(char *)) . . .

No, No, NO, NO!  C does that for you.  See section A6.6 in K&R-II, or Appendix
A, 7.4, in K&R-I .

...  which leaves one right back in the pigpen wondering how to cast this
> greater integer as in 

> 	p = (c + (char *)( i * sizeof(char *) );

What, praythee tell WHAT, is this meant to do?

Let's look at plain old analytic geometry for a moment.  You can multiply a
scalar times a scalar.  You can multiply a scalar by a vector.  ``Multiplying''
a vector by a vector is an entirely different thing; there are two kinds, but
neither corresponds to the multiplication permitted between a scalar and a
vector.

> I get the feeling that one isn't allowed pointer arithmetic at all.
> It only seems to allow such things as " &(foo[bar]) - foo ", where it
> is 100% certain that both operands point to the same data segment.

See the above-mentioned sections to determine just what operations are
defined and just what they are defined as.  There are really good and useful
operations defined with meaningful sets of operators.  What you've written
above is not a member of the sets of operations/operators that C defines.

C allows the addition of integers to pointers; informally, the result is
a pointer of the type of the original pointer, but offset from the original
by an amount scaled by the size of the object.

>  - I haven't checked it on other compilers.
> 
> 				--Blair

I hope that the other compilers respond in about the same way.
-- 

(This man's opinions are his own.)
From mole-end				Mark Terribile

bph@buengc.BU.EDU (Blair P. Houghton) (05/05/89)

In article <1556@auspex.auspex.com> guy@auspex.auspex.com (Guy Harris) writes:
>
>>but I find it more than unsettling that a pointer offset can not be
>>expressed and manipulated directly in the pointer type.
>
>Why?  "pointer offsets", if by that you mean "the value of one pointer
>relative to another", aren't the same sorts of objects as pointers.

viz,

	char array[100];
	char *a1, *a2;

	struct ohmigoditsgross brray[100];
	struct ohmigoditsgross *b1, *b2;

	int diffa;

	/* ...code in here setting a1, a2, b1, b2 to what they
	   really should be, within their respective arrays... */
	
	/* How far apart are they? */

	diffa = a2 - a1;  /* So far so C. */

	/* The others should be aligned. */

	b2 = b1 + diffa;  /* Did I just do that? */

I've been doing things like that for years and thinking I was getting away
with the golden eggs.

What I just did was add something that's _really_ a couple of bytes in
virtual size as though it was hundreds of bytes... if I think of them as
only indices, I'm fine.  It's when I start thinking in terms of physical
byte-slots, no matter how it's scaled, that my logical evaluator blows
a rectifier.

It seems that I can actually put a segment, a board, or an ethernet link
in between elements array[33] and array[34], and I could still get that

	a1 = array + 33;
	a2 = array + 34;

	diffa = a2 - a1;

and always expect diffa is exactly 1, even if the ethernet link separating
elements 33 and 34 of array[] is a million miles long.

I.e., scaling doesn't have to be constant.

This is nasty, but it works, and I'll buy it.

I'll stop trying to add pointers.

				--Blair
				  "Even though I want to."

peter@ficc.uu.net (Peter da Silva) (05/05/89)

Think of memory as a deck of cards. You can add 3 to the 5 of spades, and
get the 8 of spades. You can subtract the 4 of clubs from the 9 of clubs
and get 5 cards difference. But you can't add the 3 of hearts to the four
of hearts. -- you can't add pointers to pointers.

Continuing, you can't subtract the three of hearts from the four of spades.
-- you can't compare pointers of different types.
-- 
Peter da Silva, Xenix Support, Ferranti International Controls Corporation.

Business: uunet.uu.net!ficc!peter, peter@ficc.uu.net, +1 713 274 5180.
Personal: ...!texbell!sugar!peter, peter@sugar.hackercorp.com.

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

 >	/* How far apart are they? */
 >
 >	diffa = a2 - a1;  /* So far so C. */
 >
 >	/* The others should be aligned. */
 >
 >	b2 = b1 + diffa;  /* Did I just do that? */
 >
 >I've been doing things like that for years and thinking I was getting away
 >with the golden eggs.

I'm not sure what you're "getting away with".  You're setting things so
that the "difference" between "b2" and "b1" - i.e., the number of
elements between them - is the same as the "difference" between "a2" and
"a1".  If that's what you want to do, the above is a perfectly correct
and blessed way of doing it.

 >What I just did was add something that's _really_ a couple of bytes in
 >virtual size as though it was hundreds of bytes... if I think of them as
 >only indices, I'm fine.  It's when I start thinking in terms of physical
 >byte-slots, no matter how it's scaled, that my logical evaluator blows
 >a rectifier.

Well, my logical evaluator just blew on "really a couple of bytes in
virtual size as though it (were) hundreds of bytes"; I'm not sure what
you mean by that.  By "a couple of bytes in virtual size" do you really
mean "a couple of *elements*" (i.e., if the "struct" in question is 100
bytes long, and "diffa" is 2, then "b1" and "b2" are a couple of
*elements* away, but probably a couple of hundred *bytes* away)?

Another way of thinking of pointers is that a pointer to an array
element of type "t" is of a type that's a "superset" of the type
"pointer to type 't'", in some sense - it carries more baggage with it,
in that it not only indirectly represents the object to which it points
(as a pointer of type "pointer to type 't'" does) but it also represents
its position in the array to which the object to which it points
belongs.

In most C implementations, this information is implicit, in some sense,
in the address stored in that pointer - i.e., given the address of the
zeroth element of the array, and the type of the elements of the array
(and hence their size in storage units), and the address of the element
in question, you can compute the array index.

However, I could imagine a C implementation in which that information
was really carried around with the pointer - one that does bounds
checking on all array references, for example.  (I vaguely remember
something that led me to believe that a C implementation on a Symbolics
LISP machine did precisely that - is this true?  Does Saber C do
anything like that?)

@begin(Digression)

The pointer might contain three addresses - the address to which it
refers, the address of the first element of the array to which what it
points to belongs, and the address of the last element of that array (or
the address "one past" the address of that element).  (If the pointer
pointed to a scalar, it could be treated as pointing to the only member
of a one-element array.)

In such an implementation, "p + i" might be implemented as "add i*sizeof
(array element) to the address of the element to which 'p' pointers, and
then check whether the resulting pointer lies within the range specified
by the other two pointers, and barf if it isn't; leave the other two
pointers alone"; "p - q" might first check that the two "first element"
and "last element" pointers are the same, and barf if they aren't. 

"malloc" might return a pointer whose "current element" and "first
element" pointers are the same, and whose "last element" pointer has a
value that's the sum of the address of the first element and the number
of bytes allocated (the cast operation might check that the number of
bytes allocated is actually a multiple of the size of an array element).
"realloc" would return a pointer with the same "current element" and
"first element" pointers - after perhaps checking that they were the
same on input - and with a "last element" pointer updated according to
the new size.

@end(Digression)

 >It seems that I can actually put a segment, a board, or an ethernet link
 >in between elements array[33] and array[34], and I could still get that
 >
 >	a1 = array + 33;
 >	a2 = array + 34;
 >
 >	diffa = a2 - a1;
 >
 >and always expect diffa is exactly 1, even if the ethernet link separating
 >elements 33 and 34 of array[] is a million miles long.

You got it.  Pointer/integer addition, and pointer/pointer subtraction,
is *defined* to work that way.

 >I.e., scaling doesn't have to be constant.

"Scaling", in the sense of the commonly-imagined (and commonly present)
multiplication on pointer/integer addition and division on
pointer/pointer subtraction, is a characteristic of the implementation,
not a part of the language.  Most C implementations - possibly all
current ones - work "the way you expect them to", but that doesn't mean
it's part of the language.

gwyn@smoke.BRL.MIL (Doug Gwyn) (05/17/89)

In article <406@skye.ed.ac.uk> richard@aiai.UUCP (Richard Tobin) writes:
>>Addition of pointers is a meaningless operation.
>Not always.
>  t = p + q;

But you haven't told us what this means!
What properties does t hypothetically have?
What is its type hypothetically supposed to be?
What can one legally do with it?
(Apparently, subtracting r is legal?  What are the official criteria?)

Other postings have explained why we don't think a reasonable, consistent
model for this feature is possible.

trebor@biar.UUCP (Robert J Woodhead) (05/17/89)

In article <406@skye.ed.ac.uk> richard@aiai.UUCP (Richard Tobin) writes:
>>Addition of pointers is a meaningless operation.
>Not always.  (I'm not discussing whether it's legal in C, just whether it's
>meaningless.)

Unfortunately, all the examples you provide depend on the various pointers
pointing into a particular data structure.  What with pointers being
modified inside of functions, etc, etc, it is very difficult for a
compiler to determine that a particular pointer ``addition'' is safe
or not.

The bottom line is, meaningless or not, it is a stupid and dangerous
programming practice that will come back to haunt you, and it removes
semantic information from your program that a decent compiler could
use to your advantage.  Finally, anyone unfortunate enough to be
inflicted with the task of maintaining your code will be seriously
tempted to invoke a voodoo death curse upon you.

	Join the programmers arrayed against pointer addition.
	Just Say No to bugs.

-- 
Robert J Woodhead, Biar Games, Inc.  !uunet!biar!trebor | trebor@biar.UUCP
"The lamb will lie down with the lion, but the lamb won't get much sleep."
     -- Woody Allen.

bph@buengc.BU.EDU (Blair P. Houghton) (05/17/89)

In article <10276@smoke.BRL.MIL> gwyn@brl.arpa (Doug Gwyn) writes:
>In article <406@skye.ed.ac.uk> richard@aiai.UUCP (Richard Tobin) writes:
>>>Addition of pointers is a meaningless operation.
>>Not always.
[char *t, *p, *q]
>>  t = p + q;
>
>But you haven't told us what this means!

It means that you lose the argument, Doug.

>What properties does t hypothetically have?

It has the property that you can now subtract

    char *pnew, *r;
    pnew = t - r

and expect pnew to point to the location referred to p that is
the same offset as q is referred to r.

It's one heck of an optimization if, for some reason, the subtraction
appears in a loop, and the addition does not.

>What is its type hypothetically supposed to be?

char *

>What can one legally do with it?

What one can legally do between (consenting) integers?

>(Apparently, subtracting r is legal?  What are the official criteria?)

Ask yer second-grade teacher, or get another career.

>Other postings have explained why we don't think a reasonable, consistent
>model for this feature is possible.

"Why we don't think...possible"??  Not only is it possible, it's sensible.
As to whether we think it is so, that is irrelevant.  We don't think
fusion is possible, either, unless we consider that it's going on all
over the place (well, not _all_ over the place, but in all those jillions
of stars...!)

				--Blair
				  "Introducing N.O.C.W.A.P.: The National
				   Organization of Code Writers for
				   Addable Pointers."

chris@mimsy.UUCP (Chris Torek) (05/18/89)

In article <2890@buengc.BU.EDU> bph@buengc.BU.EDU (Blair P. Houghton) writes:
[char *t, *p, *q; t = p + q;]

>[t] has the property that you can now subtract
>
>    char *pnew, *r;
>    pnew = t - r
>
>and expect pnew to point to the location referred to p that is
>the same offset as q is referred to r.
>
>It's one heck of an optimization if, for some reason, the subtraction
>appears in a loop, and the addition does not.

I cannot think of a realistic example of this.  Anyway, pointer
addition (including the `hidden scaling') is cheap in loops, since
multiplies almost always strength-reduce to adds (and, since the
multiply is by a constant, even if it cannot be reduced to addition, it
*can* be implemented as shift-add-subtract).

Anyway, consider another argument against pointer+pointer addition:

Suppose we have a segmented architecture, in which each object is
always placed in its own segment (which is made just big enough to
address that object and one byte beyond that object).  It would
then be desirable for pointer+integer operations to overflow at
the edge of the segment, so that

	p = &arr[0]; p--;

causes a trap, as does

	p = &arr[sizeof(arr)/sizeof(*arr)]; p++;

But if all pointer arithmetic causes overflow at the end of the
segment, then given pointers (p,q) to the same segment, p+q is likely
to cause an overflow trap.  If the machine is a tagged architecture, it
is possible---even likely---that integer operations will not produce
the proper result, so that p+q (and (p+q)-q) cannot be done as an
unsigned integer add, and might well cost a library call to avoid
overflow traps, sending your hypothetical speed advantage right down
the sewer.
-- 
In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 7163)
Domain:	chris@mimsy.umd.edu	Path:	uunet!mimsy!chris

peter@ficc.uu.net (Peter da Silva) (05/18/89)

In article <561@biar.UUCP>, trebor@biar.UUCP (Robert J Woodhead) writes:
> Unfortunately, all the examples you provide depend on the various pointers
> pointing into a particular data structure.

Which is also true of pointer subtraction.

Personally, I'm against pointer addition until such time as a reasonable
type for the result can be found. It is not a pointer.
-- 
Peter da Silva, Xenix Support, Ferranti International Controls Corporation.

Business: uunet.uu.net!ficc!peter, peter@ficc.uu.net, +1 713 274 5180.
Personal: ...!texbell!sugar!peter, peter@sugar.hackercorp.com.

gwyn@smoke.BRL.MIL (Doug Gwyn) (05/18/89)

In article <2890@buengc.BU.EDU> bph@buengc.bu.edu (Blair P. Houghton) writes:
->What can one legally do with it?
-What one can legally do between (consenting) integers?
->(Apparently, subtracting r is legal?  What are the official criteria?)
-Ask yer second-grade teacher, or get another career.

You've managed to convince me (and probably others) that you don't
have an inkling what it takes to specify programming language semantics.

usenet@TSfR.UUCP (usenet) (05/18/89)

In article <2890@buengc.BU.EDU> bph@buengc.bu.edu (Blair P. Houghton) writes:
[more discussion of the properties of pointer+pointer]
>
>>What is its type hypothetically supposed to be?
>
>char *
>
>>What can one legally do with it?
>
>What one can legally do between (consenting) integers?

  Eeek.  Hopefully not.  If it's integerish, it associates & commutes,
  and if it's a pointer, well....

    pointer-pointer yields an int

  replace a pointer with a pointer+pointer....

    (pointer+pointer)-pointer yields an int

  then rearrange the parenthesis....

    pointer+(pointer-pointer) yields an int

  you'd get (using pointer-pointer yields an int) ...

    pointer+int yields an int

  which conflicts with...

    pointer+int yields a pointer

> ... Not only is it possible, it's sensible.

  Not really, not with the abilities you give it above.

  What does pointer+pointer give you, aside from clever loop optimizations?
  Wouldn't the task of loop optimizing be better served by making a type
  that holds pointer+pointer values and that can have a pointer subtracted
  from it to yield another pointer, but doesn't allow any other operation?



   -david parsons
   -orc@pell.uucp

bengsig@oracle.nl (Bjorn Engsig) (05/18/89)

>>In article <406@skye.ed.ac.uk> richard@aiai.UUCP (Richard Tobin) writes:
>>>  t = p + q;
>>
>In article <10276@smoke.BRL.MIL> gwyn@brl.arpa (Doug Gwyn) writes:
>>But you haven't told us what this means!
>
In article <2890@buengc.BU.EDU> bph@buengc.bu.edu (Blair P. Houghton) writes:
>It means that you lose the argument, Doug.
[I hope I got the quotations right]

Pointer addition IS meaningless.  Let's take an example of a 3 bit machine
with only 0, 1, 2, ... , 7 as the only addresses.  Let's also declare

char *p, *q;

and let p==3 and q==5.  Then what is p+q?  Which type does it have?  The
presumed answer of '8' cannot be stored in this machine.

>
>It's one heck of an optimization if, for some reason, the subtraction
>appears in a loop, and the addition does not.
No, it probably would not be.  Since by the example above, it is seen
that you would not be able to represent the pointer sum in a single word.

>>What is its type hypothetically supposed to be?
>
>char *
This fails completely.  If char *z = p + q (p and q from above) the what
is the significance of *z?

In article <10276@smoke.BRL.MIL> gwyn@brl.arpa (Doug Gwyn) writes:
>>Other postings have explained why we don't think a reasonable, consistent
>>model for this feature is possible.
True.

>				--Blair
>				  "Introducing N.O.C.W.A.P.: The National
>				   Organization of Code Writers for
>				   Addable Pointers."
Don't count me as a member!

BTW, what is the sum of the two 'pointers' earth *russia, *southamerica :

58 45' 22" north, 43 45' 45" east 
and
23 47' 19" south, 95 13' 18" west

(The difference, of course, is a direction and some number of kilometers)


-- 
Bjorn Engsig, ORACLE Europe         \ /    "Hofstadter's Law:  It always takes
Path:   mcvax!orcenl!bengsig         X      longer than you expect, even if you
Domain: bengsig@oracle.nl           / \     take into account Hofstadter's Law"

gsh7w@astsun1.acc.Virginia.EDU (Greg Hennessy) (05/18/89)

In article <334.nlhp3@oracle.nl> bengsig@oracle.nl (Bjorn Engsig) writes:
#Pointer addition IS meaningless.  Let's take an example of a 3 bit machine
#with only 0, 1, 2, ... , 7 as the only addresses.  Let's also declare
#
#char *p, *q;
#
#and let p==3 and q==5.  Then what is p+q?  Which type does it have?  The
#presumed answer of '8' cannot be stored in this machine.
#

Then why can't one say "Integer addition IS meaningless. Let's take an
example of a 16 bit machine. Let's also declare

int i,j;

and let i == 32000 and q == 32767. Then what is I+j? Which type does
it have? The presumed answer of `64767' cannot be stored in this
machine. 

-Greg Hennessy, University of Virginia
 USPS Mail:     Astronomy Department, Charlottesville, VA 22903-2475 USA
 Internet:      gsh7w@virginia.edu  
 UUCP:		...!uunet!virginia!gsh7w

hamish@unisoft.UUCP (Hamish Reid) (05/19/89)

In article <2890@buengc.BU.EDU> bph@buengc.bu.edu (Blair P. Houghton) writes
about adding two pointers in C, along with the amusingly gratuitous:
	"Ask yer second-grade teacher, or get another career"
addressed to Doug Gwynn....
 
Blair, you still haven't answered the question.

What does it mean in C to add two pointers (or locations? Two
addresses?) And what is the type of the result? And why would you
seriously want to try it anyway? (Don't assume any particular
implementation of pointers - it's deliberately opaque - so non-reasons
like loop effciency are out - I can understand that under
severaly-restricted conditions where all implementation details are
well-understood that it occasionally makes some sort of sense - but
we're talking C here, not "brand X's C on machine Y under operating
system Z").

Think about it all slightly differently. ***!!Dangerous Analogy Ahead -
Proceed With Caution!!*** Let's try a similar thing - let's try to add
two street locations. What does it mean to add (say) 2052 McGee Ave to
2062 McGee? Or even to subtract 2052 McGee from 2062 (or, *horror!!*,
the reverse...). You can even assume that they are in the same city
block (though in real life they're not :-)).

What does the result *mean*? In C terms, what is the type of the
result? Is it an address? Or is it actual apartment objects? Or
what...? Adding the two street addresses is a poorly-defined operation;
you can make it well-defined if you like, using formal methods, and
redefining the semantics/types/etc of street addresses, etc, but the
resulting semantics will contradict our intuitive ideas about these
things. Fine, if you like that sort of thing. Don't try the same with C
unless there's some real point, and it is a well-understood change.

Dangerous Analogy, again - it makes some sort of sense to add (say) "8"
(units unspecified but generally understood) to 2052 McGee; in some
reasonably-well understood intuitive sense it probably means something
like move 8 apartments (note type and implicit scaling here) to the
south down McGee, and read the address - "2060 McGee" (actually, the
wrong answer - it's not the same block - but we can allow for that if
we know the particular implementation...).  This is *not* the same as
adding two actual addresses.

Blair, a constructive challenge:

Post, to this newsgroup, a formal semantics definition of some proposed
changes to C that would allow you to happily and meaningfully add C
pointers as they are currently defined. You can use any reasonable
formal semantics (my preference would be some form of Plotkin- or
Milner-esque operational semantics (a la the LFCS stuff), or Natural
Semantics, or if you have to, some sort of denotational semantics), and
a small amount of handwaving, but it had better formally address the
types of the operands and the type of the result; and show how it is
compatible with the rest of C's semantics. I think *you'll* find it
difficult, but I'm definitely *not* saying it can't be done. When
you've done that, you can go off and tell Doug Gwynn to get a new
career or ask his second grade teacher....

Until we see this formal semantics, many of us will remain convinced
that you still do not have a totally clear grasp of pointers - or C for
that matter. And apologies to those who notice these things, for any
looses analogies or handwaving above, but I think this discussion just
seems to revolve round and round and I'm getting careless....

Cheers,
	Hamish
-----------------------------------------------------------------------------
Hamish Reid             UniSoft Corp, 6121 Hollis St, Emeryville CA 94608 USA
+1-415-420-6400         hamish@unisoft.com,         ...!uunet!unisoft!hamish

hamish@unisoft.UUCP (Hamish Reid) (05/19/89)

I can't stand it any longer...

In article <2890@buengc.BU.EDU> bph@buengc.bu.edu (Blair P. Houghton) writes:
>
>>What properties does t hypothetically have?
>
>It has the property that you can now subtract
>
>    char *pnew, *r;
>    pnew = t - r
>
>and expect pnew to point to the location referred to p that is
>the same offset as q is referred to r.
 
Let's try this just one more time (but see also my other posting
answering Blair's more general points):

Blair	- what is the type of the result of subtracting one pointer
	from another?

	[Hint: it's not an address unless you cast it that way - and
	then it wouldn't in general be a meaningful address]

	- what is the *difference* between two pointers (a la
	subtraction)?

	[Hint: it's not an address unless you cast it that way - and
	then it wouldn't be a meaningful address]

	- what is the type of "t" above?

	[Hint: As the original poster (Tobin?) pointed out, it's not a
	char *, nor is it really well-defined).]

>>[Doug Gwynn:] Other postings have explained why we don't think a reasonable,
>>consistent model for this feature is possible.
>
>"Why we don't think...possible"??  Not only is it possible, it's sensible.
>As to whether we think it is so, that is irrelevant.

You might want to ponder who the "we" is above. Doug Gwynn and the rest
of the Ansi C standards commitee? Concerned Citizens for C Programming
Semantics (:-))?  We poor folks in the C semantics and/or
compiler-writing community?  But gee, Blair Houghton (the original Man
With The Pointer Scaling Problem) says it's possible, it's sensible, so
it *must* be so. QED. RIP. Etc.

>We don't think
>fusion is possible, either, unless we consider that it's going on all
>over the place (well, not _all_ over the place, but in all those jillions
>of stars...!)

Speak for yourself. That was the Royal "we", I presume? There's little
else that would account for the imperiously ignorant tone of your
posting...

	Hamish
-----------------------------------------------------------------------------
Hamish Reid             UniSoft Corp, 6121 Hollis St, Emeryville CA 94608 USA
+1-415-420-6400         hamish@unisoft.com,         ...!uunet!unisoft!hamish

bph@buengc.BU.EDU (Blair P. Houghton) (05/19/89)

In article <17569@mimsy.UUCP> chris@mimsy.UUCP (Chris Torek) writes:
>In article <2890@buengc.BU.EDU> bph@buengc.BU.EDU (Blair P. Houghton) writes:
[argument for allowing pointer addition so we can hand-optimize a loop]
>
>I cannot think of a realistic example of this.

And I don't know why we need arrays at all...or Pascal, for that matter.
:-) :-) :-) :-) :-) :-) :-) :-) :-) :-) :-) :-) :-) :-) :-) :-) :-) :-)

>Anyway, consider another argument against pointer+pointer addition:
>
>Suppose we have a segmented architecture, in which each object is
>always placed in its own segment (which is made just big enough to
[...continues to argue that adding pointers may result in segment-end
overrun...]

You're using an architecture to specify C.  Is that not a no-no?

As I think earlier foistings on this thread have illustrated, it
is fallacious to expect that pointers point into an identifiable,
or even coherent, memory space.  If I put together a string, say
"foobazz", and my compiler puts the `foo' on this Encore and stores
the `bazz\0' on a Sun at CMU, but can still find it when it comes
time to dereference 5["foobazz"], then that's legal C.  Awful, slow,
unreliable, and insane, maybe.  Still C.  If it decides to store
it as `f z o z o a b \0', then it's still C, as long as

	char *a="foobazz";
	printf("%s",a);

still emits `foobazz'.

You're using C for assembly-language operations if you worry about
segmentation at all.

Further, the examples you give are not limited to pointer+pointer
arithmetic.  They'd result in over/underflow even if done in
proper pointer+int form.

>is possible---even likely---that integer operations will not produce
>the proper result, so that p+q (and (p+q)-q) cannot be done as an
>unsigned integer add, and might well cost a library call to avoid
>overflow traps, sending your hypothetical speed advantage right down
>the sewer.

The same would be true if we were trying to add unsigned integers
that weren't pointers at all.  Or a couple of really big floats...

				--Blair
				  "Really big.  Bigger than the
				   ones in the Rose Parade..."

bph@buengc.BU.EDU (Blair P. Houghton) (05/19/89)

In article <546@TSfR.UUCP> orc@TSfR.UUCP (David L. Parsons) writes:
>In article <2890@buengc.BU.EDU> bph@buengc.bu.edu (Blair P. Houghton) writes:
>[more discussion of the properties of pointer+pointer]
>>
>>>What can one legally do with it?
>>
>>What one can legally do between (consenting) integers?

[...uses the fact that pointer-pointer now returns int to show how
associativity of pointer addition would break if we allowed pointer+pointer...]

So, like, make pointer-pointer return the pointer.

make it necessary to do pointer+(pointer_type *)int to get the
current functionality of pointer+int, but leave it possible to
have an implicit cast (i.e. an automatic promotion) when adding
pointers and integers.  All that stuff about float+int could
apply to pointer+int.

>  What does pointer+pointer give you, aside from clever loop optimizations?

Hey.  It's arcane.  So is calloc().  Then you find somewhere to use it,
and you're hopping with joy.  Jeez.  What does C give you, aside from
not being Pascal?

Allowing pointer addition and treating pointers as types would make
pointer arithmetic a consistent thing.  I spent a long time thinking
it was, and never wrote any code that broke because of it, because
I'd never seen a need to use pointer+pointer, and was satisfied
with what pointer+int_as_offset.  I also didn't use casts at all for
the first few years, not having found a need for them.  I'm only
now getting into doing my own multiple-file programs.  I didn't see
a need for it, though others did.  So, one of these days I'll find
a situation, some few examples of which we've seen already, where I
will really want to do pointer+pointer without having to go through
(unsigned_int) pointer + (unsigned int) pointer.

				--Blair
				  "or is that
				   (signed) --Blair"

karl@haddock.ima.isc.com (Karl Heuer) (05/19/89)

(This is not a flame.  If this continues to the point where I feel compelled
to flame, you'll recognize it as such.)

This is a lot like talking to the platygaeanists in talk.origins.  It's hard
to refute you without knowing what you already accept.

Blair, do you understand that, even though one commonly represents both points
and vectors as n-tuples of numbers, that they are conceptually different?  Do
you accept the (common and useful) laws of arithmetic for points and vectors?

(A point has a position; a vector has a magnitude and direction.  Adding or
subtracting vectors gives you another vector.  Adding a vector to a point
gives you another point.  Subtracting two points gives you a vector.)

Does it bother you that when you multiply two lengths, you get an area rather
than another length?  Or that the ratio of two lengths is dimensionless?
Pointers are additive rather than multiplicative, but the principle is the
same.

Karl W. Z. Heuer (ima!haddock!karl or karl@haddock.isc.com), The Walking Lint

usenet@TSfR.UUCP (usenet) (05/19/89)

In article <2908@buengc.BU.EDU> bph@buengc.bu.edu (Blair P. Houghton) writes:
>In article <546@TSfR.UUCP> orc@TSfR.UUCP (David L. Parsons) writes:
>>In article <2890@buengc.BU.EDU> bph@buengc.bu.edu (Blair P. Houghton) writes:
>>[more discussion of the properties of pointer+pointer]
>>>
>>>>What can one legally do with it?
>>>
>>>What one can legally do between (consenting) integers?
>
>[...uses the fact that pointer-pointer now returns int to show how
>associativity of pointer addition would break if we allowed pointer+pointer...]
>
>So, like, make pointer-pointer return the pointer.

   So, what will happen is that a pointer will just be another scalar,
but with some additional properties that aren't subject to the operators
that you'd use with a scalar? But wouldn't that kill architectures that
don't have a flat address space? Building the language around a non-linear
address space is a bad thing, yes, but isn't building it around a linear
address space just as bad?

>>  What does pointer+pointer give you, aside from clever loop optimizations?
>
>Hey.  It's arcane.  So is calloc().  Then you find somewhere to use it,
>and you're hopping with joy.  Jeez.

   I'm sorry, I said that wrong.  Your clever loop optimisation was _nice_
and I liked it, but my question is what other things are given, and _must_
you have pointer+pointer yields pointer to get it?   In the case you gave
there, pointer+pointer yields pointer_thing would do just as well, and you
don't lost pointer-pointer in the process.

>Allowing pointer addition and treating pointers as types would make
>pointer arithmetic a consistent thing.

   But they already are consistant.  They aren't consistant if you
think of them as a scalar, but a pointer isn't a scalar- it contains
an address (not a scalar) and some fieldwidth information.  The examples
given with latitude & longitute or street addresses show the difficulty
of treating the result as a pointer.

  Consider, also, << and >> and floating point numbers.
Does prohibiting these operators make floating-point arithmetic
inconsistant? (Bitshifting a float/double gives a result that's
_highly_ dependent on the FP representation used - and _what_ does
bitshifting an int a fractional amount mean?)

>So, one of these days I'll find
>a situation, some few examples of which we've seen already, where I
>will really want to do pointer+pointer...

   Yes.  But must it break the existing relationship between pointers
and integers?


   -david parsons
   -orc@pell.uucp

carroll@s.cs.uiuc.edu (05/19/89)

/* Written 11:19 am  May 18, 1989 by gsh7w@astsun1.acc.Virginia.EDU in s.cs.uiuc.edu:comp.lang.c */
#In article <334.nlhp3@oracle.nl> bengsig@oracle.nl (Bjorn Engsig) writes:
##[ pointer overflow example ]
#Then why can't one say "Integer addition IS meaningless. Let's take an
#example of a 16 bit machine. Let's also declare
#
#int i,j;
#
#and let i == 32000 and q == 32767. Then what is I+j? Which type does
#it have? The presumed answer of `64767' cannot be stored in this
#machine. 
#
/* End of text from s.cs.uiuc.edu:comp.lang.c */

Ah, but that's an entirely different case. The programmer has complete
control over what's in those int variables, and can do overflow checking
before hand, or just use unsigned arithmetic where the result is defined
(it is mod 2^(sizeof(int)*bits_per_byte)). The programmer, however, has
_no_ control over where the pointers are, or what the actual values in
them are. He could prevent the case you talk about for int's, but how would
you do it for pointers? You may think "only in contrived examples", but
on a 3b2, all user space pointers are such that adding them _will_ cause
overflow (static/malloc are 0x8000000, stack 0xC000000). I can write portable
code that prevents int overflow. I can't do that for pointers.

Alan M. Carroll                "And there you are
carroll@s.cs.uiuc.edu           Saying 'We have the Moon, so now the Stars...'"
CS Grad / U of Ill @ Urbana    ...{ucbvax,pur-ee,convex}!s.cs.uiuc.edu!carroll

richard@aiai.ed.ac.uk (Richard Tobin) (05/20/89)

In article <334.nlhp3@oracle.nl> bengsig@oracle.nl (Bjorn Engsig) writes:

>>>In article <406@skye.ed.ac.uk> richard@aiai.UUCP (Richard Tobin) writes:
>>>>  t = p + q;

>char *p, *q;
>
>and let p==3 and q==5.  Then what is p+q?  Which type does it have?

I'm not of course suggesting that this should be added to C.  However,
I don't think it would be *impossible* to specify semantics for it.

p+q would have type "sum of 2 pointers to char".  Subtracting a pointer
to char would give a pointer to char.  Adding a pointer to char would
give "sum of 3 pointers to char".  Adding a pointer to int would give
"sum of 2 pointers to char and a pointer to int".  (We of course need
some canonicalisation here.)  Dereferencing would of course be illegal.

It might be an error to mix pointers to different aggregates.

Just to reiterate, I don't think this should really be done.  I would
hope that a compiler would generate good enough code for my original
example, but I haven't seen one that does.

-- Richard

-- 
Richard Tobin,                       JANET: R.Tobin@uk.ac.ed             
AI Applications Institute,           ARPA:  R.Tobin%uk.ac.ed@nsfnet-relay.ac.uk
Edinburgh University.                UUCP:  ...!ukc!ed.ac.uk!R.Tobin

bph@buengc.BU.EDU (Blair P. Houghton) (05/20/89)

In article <334.nlhp3@oracle.nl> bengsig@oracle.nl (Bjorn Engsig) writes:
>Pointer addition IS meaningless.

>Let's take an example of a 3 bit machine
>with only 0, 1, 2, ... , 7 as the only addresses.  Let's also declare

Urf.  Do I gotta say it again?  Yes.  I wish I could say it in double-
height, double-width, blinking, bold characters like I could if the
entire world had vt220 terminals, but, alas...

	POINTERS ARE NOT MEMORY LOCATIONS.  THAT'S A CHILDHOOD
	EXAMPLE FOR THE PASCAL-DEPROGRAMMED.  GROW UP, C-LAND 

(obligatory smiley for to mitigate the tone of that: :-).  Thanks.)

Simplest example:  you do pointer to int.  The compiler gets smart and
stores that particular int in an accumulator.  Now, tell me the address,
in octal big-endian...

>>It's one heck of an optimization if, for some reason, the subtraction
>>appears in a loop, and the addition does not.
>No, it probably would not be.  Since by the example above, it is seen
>that you would not be able to represent the pointer sum in a single word.

I can if it's not an overflow, and that's true of any form of computerized
arithmetic, so no problem.  What?  Are you going to take away my double-
precision multiplication just because it doesn't fit into a double?

See the rampant codepostings on overflow detection.

>In article <10276@smoke.BRL.MIL> gwyn@brl.arpa (Doug Gwyn) writes:
>>>Other postings have explained why we don't think a reasonable, consistent
>>>model for this feature is possible.
>True.

Irrelevant.  I don't think a reasonable, consistent model for the
universe is possible.  Does it collapse around us, therefore?

>BTW, what is the sum of the two 'pointers' earth *russia, *southamerica :
>58 45' 22" north, 43 45' 45" east
>and
>23 47' 19" south, 95 13' 18" west

what is the sum of
23 47' 19" south, 43 45' 45" east
and
4

				--Blair
				  "And you do that _daily_ in C..."

bph@buengc.BU.EDU (Blair P. Houghton) (05/20/89)

In article <2051@unisoft.UUCP> hamish@unisoft.UUCP (Hamish Reid) writes:
>Blair, you still haven't answered the question.

What question?  Okay, I got one for you:  what is the meaning of life?
Define it semantically.  Screw formalism.  Just give me a ballpark
estimate.  If it's not on my desk in the morning, life
must cease to exist.  And seriously (:-)), why would you want such
a thing to exist?  It would only screw up this nice mix of methane
gases and the arrangement of volcanic rocks we have on this planet...

>Dangerous Analogy, again - it makes some sort of sense to add (say) "8"
>(units unspecified but generally understood) to 2052 McGee; in some
>reasonably-well understood intuitive sense it probably means something
>like move 8 apartments (note type and implicit scaling here) to the
>south down McGee, and read the address - "2060 McGee" (actually, the
>wrong answer - it's not the same block - but we can allow for that if
>we know the particular implementation...).  This is *not* the same as
>adding two actual addresses.

And if you want to lob a terrorist grenade into a block of flats?  Are
you going to cobble up the average by doing all that address-integer-
address conversion one apartment at a time?  Or are you going to sum a
column of numbers, divide by the count, and throw a high, hard one at
the one nearest the result?

>Blair, a constructive challenge:

>Post, to this newsgroup, a formal semantics definition of some proposed

For a semanticist or a professional computer scientist (of which I doubt
many have the time to be wasting on this sort of thing... :) maybe, neither
of which I am.  I'm just a C-coding hacknut with a yen to see two pointers
added together.  It's not going to form a final result, surely, except
maybe for some bizarre statistical procedure or some method of
characterizing an unknown system by its transformant signature, but it is
there to allow such things as quick access to the centroid of whatever
memory map exists, among no doubt countless other uses.  Shit.  You tell
me that fifteen years ago you thought pointers were worth the extra *.

I merely came up with an idea.  It's up to the professionals to come up
with reasons that it is viable.  Just saying 'no, it's not' isn't going
to convince me that you've tried.  Everything has its pros, no matter
the cons.

Barring that, I'd do with an explanation of the decision to nonimplement
it from those who made the decision, not a load of folk-etymological
crapola from a load of casual rom-bats.  They do put 'rationale' in with
standards, you know.

>Until we see this formal semantics, many of us will remain convinced
>that you still do not have a totally clear grasp of pointers - or C for

Not relevant.  Until I see your answer to the meaning of life, in
triplicate, all of us will remain convinced that you lack a sense of
proportion.

				--Blair
				  "Lemme give you a hint:
				   it's NOT binary code..."

jas@ernie.Berkeley.EDU (Jim Shankland) (05/20/89)

In article <2919@buengc.BU.EDU> bph@buengc.bu.edu (Blair P. Houghton) writes:
>... a semanticist or a professional computer scientist ... neither
>of which I am.  I'm just a C-coding hacknut with a yen to see two pointers
>added together.

This much is abundantly clear.

You want to add two pointers together?  You can.  Here's how:

	char *cp1, *cp2, *cp3;
	...
	cp3 = (char *) ((unsigned long) cp1 + (unsigned long) cp2);

If you could do it a little less noisily than you have been :-(, many
of us would appreciate it.  Oh, and don't expect your code to be portable.
The above code has no meaning that is independent of a particular hardware
platform.  That's not C's fault, either.  If you don't understand why not,
then for Christ's sake, pick up a book or take a course or something.
Posting inane analogies and gratuitously insulting people who know more
about this than you do is a poor way to arrive at understanding.

Jim Shankland
jas@ernie.berkeley.edu

"Blame it on the lies that killed us, blame it on the truth that ran us down"

bph@buengc.BU.EDU (Blair P. Houghton) (05/20/89)

In article <2052@unisoft.UUCP> hamish@unisoft.UUCP (Hamish Reid) writes:
>I can't stand it any longer...

Take a vacation...
> 
>Let's try this just one more time (but see also my other posting
>answering Blair's more general points):
 ^^^^^^^^^
And chickens have lips like Barbara Hershey...

>Blair	- what is the type of the result of subtracting one pointer
>	from another?

What color are they?  Is it significant?  Will it overflow?

>	[Hint: it's not an address unless you cast it that way - and
>	then it wouldn't in general be a meaningful address]

Never said I'd dereference it.

>	- what is the *difference* between two pointers (a la
>	subtraction)?

What is the difference between two vectors (think umpty-dimensional,
not those wimpy, little 3-d spatial things; include dimensions like
flavor, color, opinion...what?  Your semantics inadequate?)

>	[Hint: it's not an address unless you cast it that way - and
>	then it wouldn't be a meaningful address]

Never said I'd dereference it, without operating to return the calculation
to the land of the memory locations (as so many want it bound...)

How many apples is -3 apples?  What can you do with them?  How much
cinnamon does it take to convince the kids they're getting dessert
in this situation?

>	- what is the type of "t" above?

curly with a crossbar, for all it's worth, Mr. Reid.

>	[Hint: As the original poster (Tobin?) pointed out, it's not a
>	char *, nor is it really well-defined).]

Original poster?  T'was me.  All I did was *(pointer + (sametype *) integer)
and discovered something I'd never noticed before.

That was two weeks ago.  You're just coming in the middle.  Mind you don't
get banana cream pie all over the back of your head.  This ain't clean, but
it ain't dangerous, neither...

As I recall, Mr. Tobin described a hypothetical 3-bit machine to argue
_against_ my position, then you claimed (see your other, more pedantic
posting) that I was describing hypothetical implementations in order
to _support_ my position...

Needless to say, I laughed out loud.  He was wrong, and so were you.
I'm not looking at implementation, and I've described some lunatic ones
to prove that using an implementation for support of an argument is
fallacious, specious, and ingermane.  Pointers are to ignore such things.
If I had the bucks, I'd build a memory that resided on eleven different
campuses, and store all my strings of eleven chars or more in eleven
different states, possibly three or four countries, one char per university.
Doesn't mean I still wouldn't want the compiler to know _how_ to handle

	char *bar;
	char *foo="elevenchars";

	bar = &4[foo] + &foo[6];
	bar -= &foo;

	fprintf(stdcontinent,"%c\n",*bar);

and print 

	s

on the output file/device/metaphysicalconstruct.

>>>[Doug Gwynn:] Other postings have explained why we don't think a reasonable,
>>>consistent model for this feature is possible.
>>
>>"Why we don't think...possible"??  Not only is it possible, it's sensible.
>>As to whether we think it is so, that is irrelevant.
>
>You might want to ponder who the "we" is above. Doug Gwynn and the rest
>of the Ansi C standards commitee?

In this case, I doubt it got to them.  I think Doug means the two or three
people on the "con" side of this argument so far.

>Concerned Citizens for C Programming Semantics (:-))?

CCCPS?  You gotta minute?  Are you now or have you ever been a member
of a subversive pen-pal organization?  :-)

>But gee, Blair Houghton (the original Man
>With The Pointer Scaling Problem) says it's possible, it's sensible, so
>it *must* be so. QED. RIP. Etc.

R.E.S.P.E.C.T.--that's what your love means to me...
('Retha used to help me with my Fortran problems...:-)

>>We don't think
>>fusion is possible, either, unless we consider that it's going on all
>>over the place (well, not _all_ over the place, but in all those jillions
>>of stars...!)
>
>Speak for yourself. That was the Royal "we", I presume? There's little
>else that would account for the imperiously ignorant tone of your
>posting...

Speak for yourself.  I happen to think two pointers can be added.  I also
think fusion is possible, and that Cap'n Crunch does NOT stay crunchy when
you add the milk.

				--Blair
				  "And I don't think adding crunchberries
				   will improve the neutron count any,
				   either..."

bph@buengc.BU.EDU (Blair P. Houghton) (05/20/89)

In article <13189@haddock.ima.isc.com> karl@haddock.ima.isc.com (Karl Heuer) writes:
>(This is not a flame.  If this continues to the point where I feel compelled
>to flame, you'll recognize it as such.)

Sorry, you're way behind in the flame department.  Lets keep this one on
a metaphysical level and let the rationalists act like four-year-olds
(I like playing with kids, you know.  You can go down to their level with
all the confidence that you can come back up to your own.  Makes it easy
to deal with the self-professed 'compiler-writers' on the net.)

>This is a lot like talking to the platygaeanists in talk.origins.  It's hard
>to refute you without knowing what you already accept.

True, you need clairvoyance.  Well, it just makes this drag out a little more.

>Blair, do you understand that, even though one commonly represents both points
>and vectors as n-tuples of numbers, that they are conceptually different?  Do
>you accept the (common and useful) laws of arithmetic for points and vectors?

Common and useful aren't necessarily complete and all-powerful.

>(A point has a position; a vector has a magnitude and direction.  Adding or
>subtracting vectors gives you another vector.  Adding a vector to a point
>gives you another point.  Subtracting two points gives you a vector.)

Throw in the rest of multidimensional mathematics.  Add an accounting
for the age of the point (i.e., time) and maybe, to extend the idea,
add another for its political affiliation (in the US this is a
perturbed binary value :) Disturbs your sense of vectors a bit, eh?  It
does throw off the matrix operations to have to deal with objects not
all of the same dimensionality, but then you partition the problem to
the point where there is no interaction between dissimilarly-typed
objects except by multiplication, and you have something more familiar.

>Does it bother you that when you multiply two lengths, you get an area rather
>than another length?

Does it bother you that when I add two character pointers, I get yet another
character pointer?

>Or that the ratio of two lengths is dimensionless?
>Pointers are additive rather than multiplicative, but the principle is the
>same.

Could it be that adding pointers creates different things, as multiplying
lengths creates areas?  Maybe.

If I could get these bigbrain-hopefuls off the "that's exactly the way it
isn't" bandwagon and onto a train of "lemme think about this a minute",
then we'd have something.  Unfortunately, they want to waste their time
telling me I'm unglaublich for being unglaublich, and they get my best
verschimmelt act for their efforts.

				--Blair
				  "Ciao, babe."

gwyn@smoke.BRL.MIL (Doug Gwyn) (05/20/89)

In article <2919@buengc.BU.EDU> bph@buengc.bu.edu (Blair P. Houghton) writes:
>What question?  Okay, I got one for you:  what is the meaning of life?

The question presupposes intrinsicism, which is incorrect metaphysics.
Life has no intrinsic meaning; it just is what it is (a process of
self-generated, self-sustaining action).  Meaning results from a human
attempt to explain one phenomenon in terms of others.  If you can find
meaning in life, more power to you.

Ok, we've answered your question.  Your turn.

usenet@cps3xx.UUCP (Usenet file owner) (05/20/89)

in article <2922@buengc.BU.EDU>, bph@buengc.BU.EDU (Blair P. Houghton) says:
> 
> several articles of meaningless drivle.

This is comp.lang.c most of the articles I've just read from Mr Houghton
(about six) were just noise corrupting the bandwidth of this newgroup
that is more appropriate for mail to the author. I know this comment
should be mailed to Mr Houghton, but it is also appropriate to others
posting non-newsgroup related items. TAKE YOUR FLAMES ELSEWHERE!

If you wish to flame me for this post to null.newsgroup or mail to
n address in the .sig

John H. Lawitzke           UUCP: Work: ...rutgers!mailrus!frith!dale1!jhl
Dale Computer Corp., R&D               ...uunet!frith!dale1!jhl
2367 Science Parkway             Home: ...uunet!frith!ipecac!jhl      
Okemos, MI, 48864          Internet:   jhl@frith.egr.msu.edu

Tim_CDC_Roberts@cup.portal.com (05/20/89)

The meaninglessness of pointer+pointer becomes more clear if you consider
your typical relocating loader.  If I have a module with a local symbol
"x" at offset 100, and a local symbol "y" at offset 200, then the actual
values of &x and &y at run time are actually (100+relocation_value) and
(200+relocation_value).

The operation &y-&x makes some sense, because (200+r.v.) - (100+r.v.) is
simply the absolute value 100.  However, &y + &x becomes 300 + 2 x (relocation
value), and that doesn't make sense.

&x is type pointer-to-something.  &y is pointer-to-something.  &y-&x is an
integer.  But &x+&y is...what?  It doesn't point to anything so it can't be
a pointer, and yet it's not an integer because it's value varies depending on
the load address of the module.

The COMPASS assembler for the CDC Cyber series addressed this problem.  It
allowed some quite complex expressions, but you had to watch your relocations.
 X	CON	0	X is relocatable
 Y 	CON	0	Y is relocatable
 A1	SET	X	A1 is relocatable
 A2	SET	Y-X	A2 is absolute, and has the value "1".
 A3	SET	X+3	A3 is relocatable
 A4	SET	X+Y-X	A4 is relocatable; this was allowed
 A5	SET	X+Y	** ERROR: MULTIPLY RELOCATABLE SYMBOL **

Tim_CDC_Roberts@cup.portal.com                | Control Data...
...!sun!portal!cup.portal.com!tim_cdc_roberts |   ...or it will control you.

vlcek@mit-caf.MIT.EDU (Jim Vlcek) (05/20/89)

John Lawitzke writes about a certain poster who has delighted himself
lately by posting deliberately obnoxious nonsense in response to some
reasoned articles stating why adding two pointers is meaningless:

``This is comp.lang.c most of the articles I've just read from [annoying
  poster] (about six) were just noise corrupting the bandwidth of this
  newgroup that is more appropriate for mail to the author. I know
  this comment should be mailed to [annoying poster], but it is also
  appropriate to others posting non-newsgroup related items. TAKE YOUR
  FLAMES ELSEWHERE!''

A friend of mine has a small child (about three years old) who has
reached the ``why'' stage - deliberately provoking her parents with
constant ``why's'' just to see how far she can push them.  The poster
Mr. Lawitzke is talking about reminds me of this small child.

May I second Mr. Lawitzke's notion?  Let's freeze this guy out and not
respond to his articles on addition of pointers any more.  I think
that the important points of this issue have long since been settled.

Jim Vlcek (vlcek@caf.mit.edu  uunet!mit-caf!vlcek)

chris@mimsy.UUCP (Chris Torek) (05/20/89)

-In article <334.nlhp3@oracle.nl> bengsig@oracle.nl (Bjorn Engsig) writes:
->Pointer addition IS meaningless.  Let's take an example of a 3 bit machine
->with only 0, 1, 2, ... , 7 as the only addresses.  Let's also declare
->
->char *p, *q;
->
->and let p==3 and q==5.  Then what is p+q?  Which type does it have?  The
->presumed answer of '8' cannot be stored in this machine.

In article <1513@hudson.acc.virginia.edu> gsh7w@astsun1.acc.Virginia.EDU
(Greg Hennessy) writes:
-Then why can't one say "Integer addition IS meaningless. Let's take an
-example of a 16 bit machine. Let's also declare
-
-int i,j;
-
-and let i == 32000 and q == 32767. Then what is I+j? Which type does
-it have? The presumed answer of `64767' cannot be stored in this
-machine. 

Indeed, and the result of the addition is therefore undefined.  On
some machines you get an apparently nonsense answer (-769) and on
others you get a runtime error.  The difference between this and
pointer addition is that correct code can guarantee proper integer
values before addition, but cannot guarantee proper pointer values
before addition.  (You may not portably inspect a pointer's value.)
-- 
In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 7163)
Domain:	chris@mimsy.umd.edu	Path:	uunet!mimsy!chris

chris@mimsy.UUCP (Chris Torek) (05/20/89)

>>In article <2890@buengc.BU.EDU> bph@buengc.BU.EDU (Blair P. Houghton)
presented an
>[argument for allowing pointer addition so we can hand-optimize a loop]
(his paraphrase).

>In article <17569@mimsy.UUCP> I commented:
>>I cannot think of a realistic example of this.

In article <2906@buengc.BU.EDU> bph@buengc.BU.EDU (Blair P. Houghton) writes:
>And I don't know why we need arrays at all...or Pascal, for that matter.
>:-) :-) :-) :-) :-) :-) :-) :-) :-) :-) :-) :-) :-) :-) :-) :-) :-) :-)

Actually, I was wishing you had provided one so I could shoot it down. :-)
(No fair making up straw men....)

Back to me:
>>Anyway, consider another argument against pointer+pointer addition:
>>Suppose we have a segmented architecture, ....

>You're using an architecture to specify C.  Is that not a no-no?

It might be, but that is not what I did.  A better analogy is found
in mathematics:  To prove a statement, you must show that it is
always true.  To disprove it, a single counterexample suffices.

[much deleted]

>Further, the examples you give are not limited to pointer+pointer
>arithmetic.  They'd result in over/underflow even if done in
>proper pointer+int form.

Not so.  (My `examples' were only to describe the behaviour of
a hypothetical architecture; I did not provide an example of pointer
addition.)  In any case, if you will consider for a bit you can
come up values for the following:

	pointer_type p, q, r;
	integral_type pqdiff;

	r = (p + q) / 2;	/* p+q overflows */
	r = p + (q - p) / 2;	/* no subexpression overflows */

>The same would be true if we were trying to add unsigned integers
>that weren't pointers at all.

No; unsigned arithemetic is modular arithmetic.  (It is also quite
slow on some architectures.)

>Or a couple of really big floats...

It is true that in

	double a, b, avg;
	...
	avg = (a + b) / 2.0;

the computation of (a+b) might overflow.  To avoid this, a careful
programmer will use

	avg = a + (b - a) / 2.0;

where it matters.  The key difference between this and the pointer
version is that one can portably write

	#define SAFE 10000.0	/* see pANS for a larger safe value */
	if (a < SAFE && b < SAFE)
		avg = (a + b) / 2.0;
	else
		avg = a + (b - a) / 2.0;

whereas there is no way to portably write

	if (p < ??? && q < ???) /* cannot fill in ??? portably */
		avg_of_p_and_q = (p + q) / 2;
	else
		avg_of_p_and_q = p + (q - p) / 2;

(as I mentioned in an article just posted moments ago).
-- 
In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 7163)
Domain:	chris@mimsy.umd.edu	Path:	uunet!mimsy!chris

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

 >Needless to say, I laughed out loud.  He was wrong, and so were you.
 >I'm not looking at implementation, and I've described some lunatic ones
 >to prove that using an implementation for support of an argument is
 >fallacious, specious, and ingermane.  Pointers are to ignore such things.
 >If I had the bucks, I'd build a memory that resided on eleven different
 >campuses, and store all my strings of eleven chars or more in eleven
 >different states, possibly three or four countries, one char per university.
 >Doesn't mean I still wouldn't want the compiler to know _how_ to handle
 >
 >	char *bar;
 >	char *foo="elevenchars";
 >
 >	bar = &4[foo] + &foo[6];
 >	bar -= &foo;
 >
 >	fprintf(stdcontinent,"%c\n",*bar);
 >
 >and print 
 >
 >	s
 >
 >on the output file/device/metaphysicalconstruct.

Well, then, in that case you, the person proposing the notion of
"addition of pointers", must:

	1) supply an implementation-independent meaning for addition
	   of pointers, sufficient to allow the implementer of the
	   compiler to know how addition of pointers from said different
	   states is to be interpreted;

or

	2) leave it up to somebody else to supply such a meaning, and be
	   willing at some point to accept their assertion that it can't
	   be done if they so assert (otherwise, unbounded amounts of
	   your time *and* their time can be spent arguing the point,
	   and while you may not mind this, I suspect they might);

if you actually want this feature accepted.  (*Somebody* has to give it
a meaning, otherwise there are no constraints on the implementer - they
can just say "the sum of two pointers, both of some given type, is a
null pointer of that given type" and leave it at that; such a meaning
wouldn't be particularly useful.)

I take it from your insistence that the implementation doesn't enter
into it, and that pointers aren't memory addresses, means that defining
pointer addition as "treat the bits in the pointers as if they were the
bits of some integral type, add the values you get from this operation,
and treat the bits of the result as if they were the bits of the pointer
type in question" isn't an acceptable meaning for the operation.  I
suspect you'd find it unacceptable, especially on, say, a machine with a
segmented architecture....

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

>Does it bother you that when I add two character pointers, I get yet another
>character pointer?

It does if you can't specify fairly precisely to which "char" object the
new character points, given a specification of the "char" objects to
which the original ones pointed.

>Could it be that adding pointers creates different things, as multiplying
>lengths creates areas?  Maybe.

If that were true, it would *definitely* bother me that when you add two
character pointers, you get another character pointer; either adding
pointers creates different things or it doesn't.

*Seriously*, if you want the "bigbrain-hopefuls" to "think about (this
idea) a minute", you'll need to make it a bit more concrete, so that
they perceive the probability of the idea being an Exciting New Idea as
sufficiently higher than the probability of it being The Product Of
Confusion to make it worth their while to consider it.  (No, I can think
of few, if any, people who can pursue *every* idea that comes by, in the
hopes that it *might* be worth it.  Do you read *every* article in
*every* newsgroup on USENET?  Do you buy *every* newspaper, or magazine,
or book, you see on the newsstand and read it cover-to-cover?)

scjones@sdrc.UUCP (Larry Jones) (05/21/89)

In article <2922@buengc.BU.EDU>, bph@buengc.BU.EDU (Blair P. Houghton) writes:
> Could it be that adding pointers creates different things, as multiplying
> lengths creates areas?  Maybe.

Yes!  However, adding pointers is more like multiplying areas --
it creates some new thing, but we don't have any word to describe
the result.  Why not?  Probably because most people haven't felt
a need for one -- the result doesn't have any physical analog,
nor does it have any particularly interesting properties (other
than you can reverse the operation to get back what you started
with).

Pointer addition has an additional problem, however.  We know how
to multiply areas because area is represented as a scaler value
and we know how to multiply scalars.  On the other hand, pointers
are NOT scalars and we just don't know how to add them.  At the
risk of attracting snide remarks, let me try yet another analogy:

Dates are pointers to days.  You can add 3 (days) to June 3, 1978
to get June 6, 1978.  You can subtract February 28, 1984 from
March 1, 1984 to get 2 (days).  But how do you add May 10, 1980
to May 20, 1980?
----
Larry Jones                         UUCP: uunet!sdrc!scjones
SDRC                                      scjones@SDRC.UU.NET
2000 Eastman Dr.                    BIX:  ltl
Milford, OH  45150-2789             AT&T: (513) 576-2070
"You can't get a body like mine in a bottle --
unless you push REAL HARD." - Judy Tenuta / Dr. Pepper

karl@haddock.ima.isc.com (Karl Heuer) (05/21/89)

In article <2922@buengc.BU.EDU> bph@buengc.bu.edu (Blair P. Houghton) writes:
>Could it be that adding pointers creates different things, as multiplying
>lengths creates areas?  Maybe.

Aha, maybe now we're getting somewhere.  I was hoping you'd realize that, if
this concept makes any sense at all, it would have to generate a new type, a
ptrsum_t.  Now, if you want to argue that ptrsum_t should exist (its major
property being that you can subtract a pointer from it and get a pointer, and
perhaps also allowing ptrsum_t/2 --> pointer), then I'll be much more
supportive than if you continue the false analogy of ptr+int vs float+int.

Even so, there's a lot of work that would need to be done to make this useful
to portable programs.  It's my opinion that it probably can't be done, and
even if it can, that it's not worth the effort.  If you'd like to prove me
wrong, go ahead.

In another article,
>And you whining toadies who do it so smugly don't give a flying fractal
>whether you cripple the language while you're at it.  Who's righter?

I think that someone who proposes that we
>make it necessary to do pointer+(pointer_type *)int to get the
>current functionality of pointer+int,
should not be one to accuse others of crippling the language.

Karl W. Z. Heuer (ima!haddock!karl or karl@haddock.isc.com), The Walking Lint

hamish@unisoft.UUCP (Hamish Reid) (05/21/89)

In article <2920@buengc.BU.EDU> bph@buengc.bu.edu (Blair P. Houghton) writes:
>In article <2052@unisoft.UUCP> hamish@unisoft.UUCP (Hamish Reid) writes:
>> 
>>Let's try this just one more time (but see also my other posting
>>answering Blair's more general points):
> ^^^^^^^^^
>And chickens have lips like Barbara Hershey...
>
>>Blair	- what is the type of the result of subtracting one pointer
>>	from another?
>
>What color are they?  Is it significant?  Will it overflow?

It's called not answering the questions.... Quick!! Look up there!!

>>	[Hint: As the original poster (Tobin?) pointed out, it's not a
>>	char *, nor is it really well-defined).]
>
>Original poster?  T'was me.  All I did was *(pointer + (sametype *) integer)
>and discovered something I'd never noticed before.

No. The original poster of the example you picked up and ran with was
Richard Tobin, article <406@skye.ed.ac.uk>; it's a shame you didn't
read the fine print attached to that example (the one involving 't')
before you bought it...

>As I recall, Mr. Tobin described a hypothetical 3-bit machine to argue
>_against_ my position, then you claimed (see your other, more pedantic
>posting) that I was describing hypothetical implementations in order
>to _support_ my position...

No. You got all of this wrong too. Bjorn Engsig, in article
<334.nlhp3@oracle.nl> described the hypothetical 3-bit machine; I said
that appeals to "loop optimisations" (etc) were irrelevant - in a
direct reference to one of your earlier reasons for allowing pointer
addition. Credit where credit's due... but then we haven't exactly come
to expect accuracy, thought, precision or even a bit of research in
postings from the Blair P. Houghton we've all come to know and
loathe...

And in article <2919@buengc.BU.EDU>:

>>Blair, a constructive challenge:

>>Post, to this newsgroup, a formal semantics definition of some proposed

>For a semanticist or a professional computer scientist (of which I doubt
>many have the time to be wasting on this sort of thing... :) maybe, neither
>of which I am.  I'm just a C-coding hacknut with a yen to see two pointers
>added together.

Clearly. I wouldn't be too proud of that fact if I were you. And you're
dead right - none of us professional compiler-writers, semanticists,
etc, would waste our time on trying to add pointer addition, in the way
you describe, to C.

>I merely came up with an idea.  It's up to the professionals to come up
>with reasons that it is viable.

And every time one of "the professionals" tells you why it's not a
good idea, you say they have the mind of a four-year-old, they're a
load of casual rom-bats, or they need to consult a second grade
teacher, etc.... Blair, you're not listening...

>Barring that, I'd do with an explanation of the decision to nonimplement
>it from those who made the decision, not a load of folk-etymological
>crapola from a load of casual rom-bats.

If you'd been *listening*, you might have heard the explanations from
exactly those who made the decisions. True, not all of us who have to
implement and define C can take the time to patiently explain, again
and again, why you are barking up the wrong tree. BTW, you display an
extraordinary level of certainty for a self-confessed neophyte - do you
know something about compiler writing, language definition, formal
semantics, etc, that the collected wisdom of the net doesn't? And that
the compiler-writers, professional computer scientists, C semanticists
(etc) that you've been arguing at don't? Not bloody likely....

>They do put 'rationale' in with standards, you know.

And it's clear you've never read them, let alone understood them....

Anyway, as promised earlier, I'm going to be a spoil-sport and bow out
now. Got too much formal C definition and compiler work to do, ya
know... and too little time to talk to brick-wall-like posters. Blair,
are you perhaps some sort of Artificial Stupidity program trying to
test us all?

	Hamish
-----------------------------------------------------------------------------
Hamish Reid             UniSoft Corp, 6121 Hollis St, Emeryville CA 94608 USA
+1-415-420-6400         hamish@unisoft.com,         ...!uunet!unisoft!hamish

peter@ficc.uu.net (Peter da Silva) (05/22/89)

In article <2918@buengc.BU.EDU>, bph@buengc.BU.EDU (Blair P. Houghton) writes:
> 	POINTERS ARE NOT MEMORY LOCATIONS.  THAT'S A CHILDHOOD
> 	EXAMPLE FOR THE PASCAL-DEPROGRAMMED.  GROW UP, C-LAND 

I'm glad you noticed that. You're the only one who seems determined to
think they are.

If pointers were simply memory locations, pointer addition would be a non-
problem. But they aren't, and it isn't. What do you get when you add
segment "xylophone-buggywhip" offset "3 marshmallows" to segment "xylophone-
buggywhip" offset "7 marshmallows"?

It may not even be possible to compute "2 * xylophone-buggywhip", even as an
intermediate. So you have to do what? Just add the offsets?

And there's nothing wrong with adding "3" to "2222 Dwight Way, Berkeley, CA".
You get "2225 Dwight Way, Berkeley, CA". But if you subtract 3 from "1900
Hayes Road, Houston, TX" you end up in the middle of "Andrau Airport".

But you can't add "2222 Dwight Way" to "2225 Dwight Way". Where are you
measuring from? And I don't think there is a "4447 Dwight Way".

(Quick Question, what's at 2222 Dwight Way?)
-- 
Peter da Silva, Xenix Support, Ferranti International Controls Corporation.

Business: uunet.uu.net!ficc!peter, peter@ficc.uu.net, +1 713 274 5180.
Personal: ...!texbell!sugar!peter, peter@sugar.hackercorp.com.

peter@ficc.uu.net (Peter da Silva) (05/22/89)

In article <2919@buengc.BU.EDU>, bph@buengc.BU.EDU (Blair P. Houghton) writes:
> Not relevant.  Until I see your answer to the meaning of life, in
> triplicate, all of us will remain convinced that you lack a sense of
> proportion.

The answer is 42. And the last thing you need, in this Universe, is a sense
of proportion. Look, the Universe is really big. I mean really really big...
-- 
Peter da Silva, Xenix Support, Ferranti International Controls Corporation.

Business: uunet.uu.net!ficc!peter, peter@ficc.uu.net, +1 713 274 5180.
Personal: ...!texbell!sugar!peter, peter@sugar.hackercorp.com.

peter@ficc.uu.net (Peter da Silva) (05/22/89)

In article <2922@buengc.BU.EDU>, bph@buengc.BU.EDU (Blair P. Houghton) writes:
> If I could get these bigbrain-hopefuls off the "that's exactly the way it
> isn't" bandwagon and onto a train of "lemme think about this a minute",
> then we'd have something.

Hey, remember me? I'm the guy who decided that your average of two pointers
was meaningful and got roundly flamed for it.

So.

I'm not on the "that's exactly the way it isn't" bandwagon, capiche?

You wanna know something.

They're right. I was wrong. You're still wrong.

> 				--Blair
> 				  "Ciao, babe."

The best part of your postings is your signatures. Maybe you should do a book
of them.
-- 
Peter da Silva, Xenix Support, Ferranti International Controls Corporation.

Business: uunet.uu.net!ficc!peter, peter@ficc.uu.net, +1 713 274 5180.
Personal: ...!texbell!sugar!peter, peter@sugar.hackercorp.com.

bengsig@oracle.nl (Bjorn Engsig) (05/22/89)

In article <334.nlhp3@oracle.nl> I wrote:
>>BTW, what is the sum of the two 'pointers' earth *russia, *southamerica :
>>58 45' 22" north, 43 45' 45" east
>>and
>>23 47' 19" south, 95 13' 18" west
>
and in article <2918@buengc.BU.EDU> bph@buengc.bu.edu (Blair P. Houghton)
replied:
>what is the sum of
>23 47' 19" south, 43 45' 45" east
>and
>4
Blair, you are totally missing my point here.  I used a geometric example to
show the nonsense in adding two pointers, and as I also pointed out in that
article, the difference between two pointers is very well defined; in this
case, however, it is not a plain number but a direction and a distance, e.g.
27 degrees, 350 km.  Your supposed counter example of adding a geometric
pointer and a number is of course invalid, since you are not adding a pointer
difference (direction, distance) to a pointer.

Exactly the same was pointed out by Karl Heuer <karl@haddock.ima.isc.com>
in article <13189@haddock.ima.isc.com>, using points in the plane [a pointer]
and vectors [a point(er) difference].

So please try to understand that adding two pointers does not yield anything
meaningful.

Let's close down the subject, there shouldn't be any more debate.
-- 
Bjorn Engsig, ORACLE Europe         \ /    "Hofstadter's Law:  It always takes
Path:   mcvax!orcenl!bengsig         X      longer than you expect, even if you
Domain: bengsig@oracle.nl           / \     take into account Hofstadter's Law"

bengsig@oracle.nl (Bjorn Engsig) (05/22/89)

In article <2922@buengc.BU.EDU> bph@buengc.bu.edu (Blair P. Houghton) writes:
>Does it bother you that when I add two character pointers, I get yet another
>character pointer?
No, you DO NOT.  We still haven't seen a posting of yours, which gives a
precise description of what you mean by pointer addition, but on the other hand,
I guess it will never come.
-- 
Bjorn Engsig, ORACLE Europe         \ /    "Hofstadter's Law:  It always takes
Path:   mcvax!orcenl!bengsig         X      longer than you expect, even if you
Domain: bengsig@oracle.nl           / \     take into account Hofstadter's Law"

mcdonald@uxe.cso.uiuc.edu (05/23/89)

/* Written  1:51 pm  May 21, 1989 by peter@ficc.uu.net in uxe.cso.uiuc.edu:comp.lang.c */
In article <2918@buengc.BU.EDU>, bph@buengc.BU.EDU (Blair P. Houghton) writes:
> 	POINTERS ARE NOT MEMORY LOCATIONS.  THAT'S A CHILDHOOD
> 	EXAMPLE FOR THE PASCAL-DEPROGRAMMED.  GROW UP, C-LAND 

I'm glad you noticed that. You're the only one who seems determined to
think they are.

If pointers were simply memory locations, pointer addition would be a non-
problem. But they aren't, and it isn't. What do you get when you add
segment "xylophone-buggywhip" offset "3 marshmallows" to segment "xylophone-
buggywhip" offset "7 marshmallows"?

-- 
Peter da Silva, Xenix Support, Ferranti International Controls Corporation.

Business: uunet.uu.net!ficc!peter, peter@ficc.uu.net, +1 713 274 5180.
Personal: ...!texbell!sugar!peter, peter@sugar.hackercorp.com.
/* End of text from uxe.cso.uiuc.edu:comp.lang.c */

I believe that pointers in C can be cast to some suitable integral type,
for example unsigned long. Then you can do what you wish with their value.
Then cast back to the pointer of your choice, and if you are suitably
knowledgeable about the target machine, the effect of your choice should
be achieved.

I simply don't understand all the flamage. There seems to be a legal
way to do what some people want to do. If it works, it works, if
it doesn't work, study some more. (For example, on the machine I
am typing this on, an IBM PS/2 Model 80, using my usual C compiler
(Microway NDPC), pointers are simply 32bit offsets from some
system-supplied origin. It is not hard to figure out what will happen
if you cast a few to unsigned int, add and subtract, and cast back.
I can easily figure out whether such an operation would give a useful
result or an illegal memory trap. Such operations are simply target-
machine dependent.)

Could somebody (by e-mail, not posting) explain why there is so much
flamage on this. Can't it simply be dismissed by the one liner
"machine and compiler dependent"? I'll agree that there is no
need to make POINTER ADDITION be legal C, since casts allow the
effect to be achieved. There are certainly flammable subjects
involving pointers, but this isn't one.


Doug McDonald

phil@ux1.cso.uiuc.edu (05/24/89)

There is a difference between pointer addition and casted pointer addition,
however.

        q = (int *) ( (int) p + 5 );

        q = p + 5;

richard@aiai.ed.ac.uk (Richard Tobin) (05/24/89)

In article <2920@buengc.BU.EDU> bph@buengc.bu.edu (Blair P. Houghton) writes:
>As I recall, Mr. Tobin described a hypothetical 3-bit machine to argue

No that was someone else.  Please check these things before posting.


-- Richard
-- 
Richard Tobin,                       JANET: R.Tobin@uk.ac.ed             
AI Applications Institute,           ARPA:  R.Tobin%uk.ac.ed@nsfnet-relay.ac.uk
Edinburgh University.                UUCP:  ...!ukc!ed.ac.uk!R.Tobin

phil@ux1.cso.uiuc.edu (05/25/89)

What about:

    long x,y,z,*q,*p,a[19];
    int i;
      .
      .
    p = a;
    q = NULL[i];  /* or even i[NULL] */
    x = *(p+q);
    q = q[1];
    y = p[q];
    q = q[1];
    z = q[p];

Obviously this is machine dependent.  But it might be useful on most machines
anyway since most implement NULL as 0.  Thus "q" will be of type pointer, but
will in fact have an OFFSET instead of an absolute value.

When I program in assembler, I usually index with offsets instead of with
integers, so I can avoid the repeated multiplies each time around the loop
that increments the offset or integer.  Thus:

    q = q[1];

might be faster depending on how well the compiler recognizes the usage of the
constant.  By generating code that directly adds the length of a "long" to the
value of "q", you avoid all the multiplies.

Alternatively in many cases, one can just increment absolute pointers as well.
There are a few cases where the same offset can be used in more than one array
because the arrays have elements of the same length/type.

--Phil howard--  <phil@ux1.cso.uiuc.edu>

chris@mimsy.UUCP (Chris Torek) (05/25/89)

In article <6200006@ux1.cso.uiuc.edu> phil@ux1.cso.uiuc.edu writes:
>    long x,y,z,*q,*p,a[19];
>    int i;
>      .
>      .
>    p = a;
>    q = NULL[i];  /* or even i[NULL] */
>    x = *(p+q);
>    q = q[1];
>    y = p[q];
>    q = q[1];
>    z = q[p];
>
>Obviously this is machine dependent.

In which case, why not write it in an existing, legal, machine-dependent
fashion instead:

	long x, y, z, q, *p, a[19];
	int i;
	...
	p = a;
	q = (long)(i * sizeof(*p));
	x = *(long *)((char *)p + q);
	q += sizeof(*p);	/* I think you meant `q = &q[1]' */
	y = *(long *)((char *)p + q);
	q += sizeof(*p);
	z = *(long *)((char *)p + q);

The casts have the effect of warning the reader that something odd
is going on.  (Personally, I would rather read

	x = a[i];
	y = a[i+1];
	z = a[i+2];

than either of the two versions above.  Chances are that a decent
compiler will generate code at least as good, if not better, for
this third version.)
-- 
In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 7163)
Domain:	chris@mimsy.umd.edu	Path:	uunet!mimsy!chris

gwyn@smoke.BRL.MIL (Doug Gwyn) (05/25/89)

In article <6200006@ux1.cso.uiuc.edu> phil@ux1.cso.uiuc.edu writes:
>What about:
>    q = NULL[i];  /* or even i[NULL] */
>    q = q[1];

Please don't do these things even if your particular compiler happens
to let you get away with it.  There is no reason to expect these to
work and on many C implementations they will fail.  There are other,
portable ways to accomplish such operations.

tcm@srhqla.UUCP (Tim Meighan) (05/26/89)

In article <2919@buengc.BU.EDU> bph@buengc.bu.edu (Blair P. Houghton) writes:

     >What question?  Okay, I got one for you:  what is the meaning of life?
     >Define it semantically.  Screw formalism.  Just give me a ballpark es-
     >timate.  If it's not on my desk in the morning, life must cease to exist.

Blair, you have now also convinced your very captive audience that you do not
know how to properly map analogies.

     >I merely came up with an idea.  It's up to the professionals to come up
     >with reasons that it is viable.  

WRONG AGAIN, dude!  One condition of a scientific idea is that it must have
tests to show that it is NOT viable, not that it IS viable.  No one else
HAS to show why it's GOOD.   That's YOUR responsibility, it's YOUR idea.
"The professionals" get to apply tests to see if the idea is JUNK.  If you 
don't allow tests to disprove your idea, you have no business pretending
you are presenting anything of possible value. 

There are many professional people on this net who live and breath
the C language.  Some of these people have indeed taken the time to
explain why your idea is NOT viable in C.  You don't care about the
explanations.  You're not even listening.

So program in C however you want.  Do it any way you feel like.  And keep
making an ass of yourself to thousands of people.  It's really amusing.

Tim Meighan
SilentRadio

"I'm sure that if I keep screaming loudly enough that the world
 IS flat, they'll just HAVE to start believing me!!!"