bph@buengc.BU.EDU (Blair P. Houghton) (05/04/89)
Hey! That's me!! :-) --vvvvvvvvvvvvvvvvv In article <2747@buengc.BU.EDU> bph@buengc.bu.edu (Blair P. Houghton) writes: > [...You've read the movie, now go see the book!!...] Thanks to all who pushed me upright. I seem to have been tottering on the brink of looneytunes for the past few days (pulling ten all-nighters in 2.5 weeks is no way to live, especially when yer a grad stoont and don't have to put up with that final-exam shit anymore. Yup. I go 40hrs sleepless because I _want_to_... %-|) Anyway, it's now well established that I've harbored a fundamental misconception about C and pointer indexing for a number of years. I think I've got it identified, and I hope someone else benefits from my story. In Jim Kingdon's emailed reply to my original posting, he mentioned that I should be wary of scaling in pointer arithmetic. I wrote back: I know all about the automatic scaling of an integer in pointer arithmetic. I've just always felt a little guilty about using what I'd interpreted to be a convenience. Rather than a proper feature of the C syntax, I'd always felt that adding an integer to a pointer was allowed as being "the obvious thing that should be done in that situation." There are lots of 'obvious' things that are _not_ implemented that way, however, and that should have been a clue. Still, I just took it for granted that what was going on was a promotion from integer to pointer, then the addition. Now I know much, much better. A pointer isn't really a data type at all. It's a different sort of beastie, germane only within a program, and therefore it is fallacious to see it as having the properties of a countable, measurable, or otherwise physical entity. The way pointers work implies that they don't refer at all to anything physical, even to memory locations. It doesn't change the fact that I'd like to be able to add and subtract pointers regardless of what trouble I _might_ get into. Considering the general level of danger incurred by programming in something so potentially obfuscatory as C, it's a small barrier to remove. The arguments of "why would you want to do _that_?" don't hold water. I counter with "Why would you want variadic functions?" and "Why would you want to define mathematical routines when you can write your own in assembler and link to them?" --Blair "And one of these days I'll know what the middle pedal on a piano is for."
gwyn@smoke.BRL.MIL (Doug Gwyn) (05/04/89)
In article <2763@buengc.BU.EDU> bph@buengc.bu.edu (Blair P. Houghton) writes:
- Now I know much, much better. A pointer isn't really a
- data type at all. It's a different sort of beastie,
- germane only within a program, and therefore it is
- fallacious to see it as having the properties of a
- countable, measurable, or otherwise physical entity.
-The way pointers work implies that they don't refer at all to
-anything physical, even to memory locations.
I don't think you have it figured out yet.
-It doesn't change the fact that I'd like to be able to add and subtract
-pointers regardless of what trouble I _might_ get into.
Fine; cast them into the appropriate integral type and do whatever
integral arithmetic your heart desires. Don't expect anyone else to
appreciate the beauty of your code when you've done this..
guy@auspex.auspex.com (Guy Harris) (05/04/89)
>It doesn't change the fact that I'd like to be able to add and subtract >pointers regardless of what trouble I _might_ get into. Considering the >general level of danger incurred by programming in something so potentially >obfuscatory as C, it's a small barrier to remove. I guess the question is "what do you expect to happen when you add pointers?" The definition of "pointer + int" doesn't refer to low-level bit-banging - i.e., the "multiply by the size of the object and then add the (binary) values of the pointer and the result of the multiplication" is perhaps more of a guide to understanding for people unfamiliar with C-style pointer addition but familiar with bit-banging, and a guide to the implementer, than a definition. (Check out the Dec. 7, 1988 draft - the "multiply by the size of the object..." stuff is relegated to a footnote.) Can you come up with a similar definition for the addition of two pointers? If not, it sounds like it may be implementation-dependent, in which case C implementations may let you do what you want by casting the pointers properly (perhaps to some integral type), in which case you *could* do what you want - you just have to say "pretty please" to the C compiler. I have no problem whatsoever with that; I *like* it when the compiler discovers I've screwed up when it detects a type mismatch - it saves me from discovering it at run time. Think of it as a fail-safe.
peter@ficc.uu.net (Peter da Silva) (05/04/89)
Basically a pointer is a cardinal, not an ordinal. -- 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.
feg@clyde.ATT.COM (Forrest Gehrke) (05/05/89)
In article <2763@buengc.BU.EDU>, bph@buengc.BU.EDU (Blair P. Houghton) writes: > > The way pointers work implies that they don't refer at all to > anything physical, even to memory locations. > On some systems, particularly one that does not deal in virtual memory, a pointer can be referring to a real memory location. Which leads me to wonder what you would do, as you insist upon being able to do, with the sum of two pointers? If you can find a use for this, why stop there? There's also multiplication and division...... > It doesn't change the fact that I'd like to be able to add and subtract ^^^ > pointers regardless of what trouble I _might_ get into. Considering the > general level of danger incurred by programming in something so potentially > obfuscatory as C, it's a small barrier to remove. The arguments of > "why would you want to do _that_?" don't hold water. I counter with > "Why would you want variadic functions?" and "Why would you want to > define mathematical routines when you can write your own in assembler > and link to them?" Perhaps this question is asked because while we can think of uses for wanting these things, we haven't thought of what we could do with the sum of pointers. You haven't yet provided any motives either. Forrest Gehrke
bph@buengc.BU.EDU (Blair P. Houghton) (05/05/89)
In article <1558@auspex.auspex.com> guy@auspex.auspex.com (Guy Harris) writes: > >Can you come up with a similar definition for the addition of two >pointers? As Gwyn said (and he thinks I rejected it, but I didn't, he should check out that I was referring to his statement, not mine...) "addition of two pointers is meaningless." Addition of 0xfffe and 0xfffe puts you over the top of a data segment and that's bogus. Add that, as I posted earlier today, I now see that the "scaling" of pointers isn't to be trusted, either, and this addition doesn't even do what it appears to do, whether that's what I want or not. Addition of two pointers? I'd never do it. Addition of two things that have pointer type? That I might do. float array[100] float *a1, *a2; float *diffa; struct gomessyourself brray[100]; struct gomessyourself *b1, *b2; /* ...Code setting the array values, and pointing a1, a2, and b1 into their respective arrays... */ dobedobedoo(array,brray,&a1,&a2,&b1); /* Want to align the pointer differences; how far apart are the a's ? */ diffa = a2 - a1; /* Bogus in normal C */ /* Now align the b's */ b2 = b1 + diffa; What does that do? It tries to add a float-pointer to a struct-ugly-pointer. Mismatch errors fill my screen with a phosphorescent radiance. And well they should. Normal C, however, allows this sort of thing by telling one to declare int diffa; and merrily arithmeticise. No warnings, no complaints, not even a bump in the great, grassy field of complacen-C.... Mind you, it's real nice to be able to do it this way, and if one couldn't, we'd all be screaming for it, but it feels the same as adding shorts, longs, and ints together haphazardly. --Blair "Okay, `long diffa'. There, you happy?"
guy@auspex.auspex.com (Guy Harris) (05/05/89)
>Normal C, however, allows this sort of thing by telling one to declare > > int diffa; > >and merrily arithmeticise. No warnings, no complaints, not even a bump >in the great, grassy field of complacen-C.... Or, even better, "ptrdiff_t diffa", in (p)ANS C at least, where "ptrdiff_t" is defined in <stddef.h>. >Mind you, it's real nice to be able to do it this way, and if one >couldn't, we'd all be screaming for it, but it feels the same as adding >shorts, longs, and ints together haphazardly. Well, think of "ptrdiff_t" as syntactic sugar-coating, or syntactic buffering to prevent an upset stomach (you remember, the little "B"s bouncing around your stomach, which don't have the sharp points that the little "A"s do, and thus don't poke into your stomach lining); you now have objects of various flavors of pointer type, of various flavors of integral type - and of a type that means "difference between pointers", although that type happens to be one of the integral types. Now, while pointers come in different types, "difference between pointers" happens to come in only one type - but then, measurements come in different types (cm, inches, grams, furlongs, fortnights, etc.), but ratios of measurements come in one type, too....
hutch@lzaz.ATT.COM (R.HUTCHISON) (05/05/89)
Re: addition of two pointers How 'bout in a binary search to find the middle char in an array of characters? midpoint_pointer = (start_pointer + end_pointer) / 2; Yes, I realize that you can... midpoint_pointer = ((end_pointer - start_pointer) / 2) + start_pointer; ... but I think people were asking when you might ever want to add two pointers and where it could possibly me meaningful. After all, if the two variables were not pointers and represented distances (in feet) and I wanted the midpoint, I might choose the first approach. Bob Hutchison lzaz!hutch
peter@ficc.uu.net (Peter da Silva) (05/06/89)
In article <563@lzaz.ATT.COM>, hutch@lzaz.ATT.COM (R.HUTCHISON) writes: > midpoint_pointer = (start_pointer + end_pointer) / 2; You're right. It's a valid operation. (what's the average of the 7 clubs and the 9 clubs?) -- 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.
dts@quad.uucp (David T. Sandberg) (05/06/89)
In article <4093@ficc.uu.net> peter@ficc.uu.net (Peter da Silva) writes: >In article <563@lzaz.ATT.COM>, hutch@lzaz.ATT.COM (R.HUTCHISON) writes: >> midpoint_pointer = (start_pointer + end_pointer) / 2; > >You're right. It's a valid operation. It is? What about when the difference between the two is an odd number of multibyte units? Writing to *midpoint_pointer after setting it up in such a fashion is going to corrupt some data (unless, of course, you *want* to modify the last byte(s) of one unit and the first byte(s) of the next ;') >(what's the average of the 7 clubs and the 9 clubs?) More to the point, what's the difference between the 7 clubs and the 8 clubs? Perhaps you mean that it is an *allowed* operation, without regards to the wisdom of same. Or perhaps you guys are only talking about char pointers (and then what happens if you run into a multibyte char machine?). -- char *david_sandberg() { return ( dts@quad.uucp || uunet!rosevax!sialis!quad!dts ); }
peter@ficc.uu.net (Peter da Silva) (05/07/89)
In article <127@quad.uucp>, dts@quad.uucp (David T. Sandberg) writes: > It is? What about when the difference between the two is an odd > number of multibyte units? You have to align the result before using it, of course. > >(what's the average of the 7 clubs and the 9 clubs?) > More to the point, what's the difference between the 7 clubs and the > 8 clubs? clubs_t clubs[13]; printf("%d\n", &clubs[7]-&clubs[8]); The result better be -1. -- 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.
mcdaniel@uicsrd.csrd.uiuc.edu (Tim McDaniel) (05/07/89)
Suppose that pointer addition means that "&A[i] + &A[j] == &A[i+j]". (Is this what you had in mind, Peter?) In a previous article, I showed that "&A[i] + &A[j] == &A[i+j]" requires (in general) that pointers be represented internally as pairs "(location,base_of_array)". To briefly recap, if we want Total = A + B; we can't just add the addresses as integers. For example, suppose that A and B point into an array Array that starts at address 100, and that A is 102 and B is 104. A+B must then be 106. Adding A+B as integers would yield 102+104 == 206, which is incorrect. We must use pairs as above and compute Total by Total.base = A.base; /* or B.base */ Total.loc = (A.loc - A.base) + B.loc; (so Total.loc = (102-100)+104 == 106, as required). In article <127@quad.uucp>, dts@quad.uucp (David T. Sandberg) writes: > More to the point, what's the difference between the 7 clubs and the > 8 clubs? I think he meant "midpoint", not "difference". In article <4097@ficc.uu.net> peter@ficc.uu.net (Peter da Silva) writes: >You have to align the result before using it, of course. I agree that these results would have to be aligned. But how? For some_type * M, * A, * B; let's compare a: M = (A + B) / 2; versus b: M = A + (B - A) / 2; a: Mid, A, and B take 6 addresses to represent: (M.loc,M.base), (A.loc,A.base), (B.loc,B.base). Assume that A and B point into the same array, so A.base==B.base. The best implementation I can think of is t = (A.loc + B.loc) / 2 /* average */ - A.base; /* begin aligning */ M.loc = (t - t % sizeof *A) + A.base; /* rest of aligning */ M.base = A.base; You see, it's not guaranteed that "(A.loc+B.loc)/2" is aligned for A.base. We have to see how far it is from A.base (the first subtraction), align that to "sizeof (some_type)" (second subtraction and the modulo), and add A.base back in to get the address. Total operation count: 1 divide (or right shift), 1 modulo (or bitwise-AND if "sizeof *A" is a power of 2), 4 adds/subtracts. Note that a modulo is usually as expensive as a divide. We can do better if A.base is known to be aligned on a "sizeof (*A)" boundary. However, many systems can't guarantee this for arbitrarily- large types. For example, if A.base was malloced, it may only be at an 8-byte boundary (for a VAX). Even if we know that A.base is so aligned (for example, if some_type is long, and all longs are so aligned), we can only improve it to t = (A.loc + B.loc) / 2; M.loc = t - t % sizeof *A; M.base = A.base; Operations: 1 divide (or right shift), 1 modulo (or bitwise-AND if "sizeof *A" is a power of two), 2 adds/subtracts. Even this solution ignores overflow for the first add. b: If no single data object takes more than half of memory, overflow is impossible. Representing the 3 pointers uses only 3 addresses: Mloc, Aloc, Bloc. Mloc = Aloc + (Bloc - Aloc) / sizeof *A / 2; Operations: 1 divide (or right shift if "sizeof *A" is a power of 2), 2 adds/subtracts. So pointer addition doubles the size of pointers, runs slower, and is susceptible to overflow. As far as I can tell, the only thing it gains us is the ability to write midpoint = (start + end) / 2; instead of /* midpoint is the midpoint of start and end, because * A + (B-A)/2 == A + B/2 - A/2 == A/2 + B/2 == (A+B)/2. */ midpoint = start + (end - start) / 2; Peter, you can't just say "let there be pointer addition", and FIAT LUX! there is pointer addition, and it is good. You have to propose an actual implementation. Furthermore, if this implementation is more costly than the current situation, you have to show that the gains outweigh the costs. You have done neither. -- Tim, the Bizarre and Oddly-Dressed Enchanter Center for ||| Internet, BITNET: mcdaniel@uicsrd.csrd.uiuc.edu Supercomputing ||| UUCP: {uunet,convex,pur-ee}!uiucuxc!uicsrd!mcdaniel Research and ||| ARPANET: mcdaniel%uicsrd@uxc.cso.uiuc.edu Development, ||| CSNET: mcdaniel%uicsrd@uiuc.csnet U of Illinois ||| DECnet: GARCON::"mcdaniel@uicsrd.csrd.uiuc.edu"
dts@quad.uucp (David T. Sandberg) (05/08/89)
In article <925@garcon.cso.uiuc.edu> mcdaniel@uicsrd.csrd.uiuc.edu (Tim McDaniel) writes: >In article <127@quad.uucp>, dts@quad.uucp (David T. Sandberg) writes: >> More to the point, what's the difference between the 7 clubs and the >> 8 clubs? > >I think he meant "midpoint", not "difference". Yes, "midpoint" is a more correct description of what I meant. In retrospect, I should consider myself fortunate that someone actually understood what I was trying to say. ;') -- char *david_sandberg() { return ( dts@quad.uucp || uunet!rosevax!sialis!quad!dts ); }
gwyn@smoke.BRL.MIL (Doug Gwyn) (05/08/89)
In article <4093@ficc.uu.net> peter@ficc.uu.net (Peter da Silva) writes: >In article <563@lzaz.ATT.COM>, hutch@lzaz.ATT.COM (R.HUTCHISON) writes: >> midpoint_pointer = (start_pointer + end_pointer) / 2; >You're right. It's a valid operation. >(what's the average of the 7 clubs and the 9 clubs?) What's the average of the 7 of clubs and the 10 of clubs? What if sizeof(club) > 1? Shouldn't we end up pointing into the middle of a club? How is any sane language definition supposed to factor in such application-specific notions of what is "appropriate" behavior? C provides a sufficiently simple way to specify exactly what is intended in such situations.
throopw@bert.dg.com (Wayne A. Throop) (05/08/89)
> bph@buengc.BU.EDU (Blair P. Houghton) > Thanks to all who pushed me upright. I think either your seat or your tray table is not yet in the full upright position, because what you say here: > I think I've got it [..that is, the misunderstanding about pointer > arithmetic..] identified, and I hope someone else benefits from > my story. In Jim Kingdon's emailed reply to my original posting, he > mentioned that I should be wary of scaling in pointer arithmetic. I > wrote back: > I know all about the automatic scaling of an integer in > pointer arithmetic. > [... and ...] > Now I know much, much better. A pointer isn't really a > data type at all. > [... and ...] > The way pointers work implies that they don't refer at all to > anything physical, even to memory locations. This is wrong. Very wrong. First off, the integer is not scaled in pointer/integer arithmetic. The pointer is. Second, pointers are data types every bit as much as floating point, or integers, or characters are. Third, pointers work as if they are references to any of the types of objects expressable in C (though not all instances of those objects can be refered to by a pointer value). The pointer is scaled so that details of particular implementation of pointer on any machine can be made portable. The details are hidden by the compiler, so that machine independant pointer manipulations can be done. This is a major innovation in C, and generally (as low level features go) a Good Thing. Pointers are data types, in that they are objects which contain information just as any other C type does. As with, say, floating point types, C remains very cagy about the the exact structure of pointer data expressed in bits. And finally pointers have well-defined operations which can be performed against them, in particular indirection and arithmetic, and well-defined meanings for the values they can take on. So I'd say they have a very good definition of what they "work as if". > It doesn't change the fact that I'd like to be able to add and subtract > pointers regardless of what trouble I _might_ get into. Considering the > general level of danger incurred by programming in something so potentially > obfuscatory as C, it's a small barrier to remove. So why try to guild the lilly? This barrier HAS been removed, in that when pointers and integers are mixed, very reasonable, machine independant semantics are attached to the process. The point is, Blair expects an object defined as one type to behave both as if it were a pointer and an offset at the same time. This is NOT sensible. -- If it could be demonstrated that any complex organ existed which coult not possibly have been formed by numerous, successive, slight modifications, my theory would absolutely break down. --- Charles Darwin -- Wayne Throop <the-known-world>!mcnc!rti!xyzzy!throopw
diamond@diamond.csl.sony.junet (Norman Diamond) (05/08/89)
In article <563@lzaz.ATT.COM> hutch@lzaz.ATT.COM (R.HUTCHISON) writes: >Re: addition of two pointers > >How 'bout in a binary search to find the middle char in an array of >characters? > > midpoint_pointer = (start_pointer + end_pointer) / 2; Yup, and if you have an array of ints? Let's see, half-way between the 1st and 6th elements, we have the 3.5th element. Well yeah, you've got chars not ints. Only the machine uses word addressing so that your pointers use some extra bits to indicate the offset within a word. If you're planning to leave your present employer before they ever have to port your code to another machine, you could do this: midpoint_pointer = (char *) (((unsigned long) start_pointer + (unsigned long) end_pointer) / 2); -- Norman Diamond, Sony Computer Science Lab (diamond%csl.sony.co.jp@relay.cs.net) The above opinions are my own. | Why are programmers criticized for If they're also your opinions, | re-inventing the wheel, when car you're infringing my copyright. | manufacturers are praised for it?
peter@ficc.uu.net (Peter da Silva) (05/08/89)
In article <925@garcon.cso.uiuc.edu>, mcdaniel@uicsrd.csrd.uiuc.edu (Tim McDaniel) writes: > Suppose that pointer addition means that "&A[i] + &A[j] == &A[i+j]". > (Is this what you had in mind, Peter?) No, I had in mind ((ptrdiff_t)&A[i]) - ((ptrdiff_t)&A[j]). It's an intermediate result only. Which you point out in great detail. > Peter, you can't just say "let there be pointer addition", and > FIAT LUX! > there is pointer addition, and it is good. You have to propose an > actual implementation. Furthermore, if this implementation is more > costly than the current situation, you have to show that the gains > outweigh the costs. You have done neither. Chill out, dude :->. I was arguing *against* it as a general operation. I was just noting that there *is* (despite my previous beliefs) an application for it. -- 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.
bph@buengc.BU.EDU (Blair P. Houghton) (05/09/89)
In article <5779@xyzzy.UUCP> throopw@bert.dg.com (Wayne A. Throop) enscreeds: >> bph@buengc.BU.EDU (Blair P. Houghton) >> Thanks to all who pushed me upright. Yeah, thanks for the whiplash... ( ;-) just kidding :-) ) >The point is, Blair expects an object defined as one type to behave both >as if it were a pointer and an offset at the same time. This is NOT sensible. Nay, I want it to behave as an object, and not as some nebulous changeling requiring maintenance-by-fiat. If one is yea-big and the other is yo-big, then I damn well want the difference between them to be yea-yo, at the very least when I _tell_ it to be so. It's sensible aplenty. The only question is: does it add sufficient functionality to justify the trouble it allows? That there's a question for the more scientific amongst this gaggle of Computo-Scientists. >If it could be demonstrated that any complex organ existed which coult not >possibly have been formed by numerous, successive, slight modifications, >my theory would absolutely break down. Interesting logic in there: "If it could...then...would absolutely" It implies that it must be that "it" could not; since therefore the theory would break down absolutely, and since the theory doesn't, then therefore "it" couldn't "be demonstrated". Good. That saves me a lot of time trying to demonstrate it. > --- Charles Darwin I get flamed by the most impressive people... --Blair "Speaking of fiat..."
stacey@hcr.UUCP (Stacey Campbell) (05/10/89)
In article <4093@ficc.uu.net> peter@ficc.UUCP writes: >In article <563@lzaz.ATT.COM>, hutch@lzaz.ATT.COM (R.HUTCHISON) writes: >> midpoint_pointer = (start_pointer + end_pointer) / 2; > >You're right. It's a valid operation. > >(what's the average of the 7 clubs and the 9 clubs?) Que? On a segmented architecture p1 + p2 blows up badly. How about; mid = start + (end - start) / 2; -- Stacey Campbell, HCR Corporation, {lsuc,utzoo,utcsri}!hcr!stacey
jzs@bridge2.ESD.3Com.Com (Jeremy A. Siegel) (05/10/89)
>>The point is, Blair expects an object defined as one type to behave both >>as if it were a pointer and an offset at the same time. This is NOT sensible. >Nay, I want it to behave as an object, and not as some nebulous changeling ^^ ^^^^^^^^^ >requiring maintenance-by-fiat. If one is yea-big and the other is yo-big, >then I damn well want the difference between them to be yea-yo, at the >very least when I _tell_ it to be so. My, my! I'd nearly stopped reading this thread; it seems to have generated so much theoretical discussion (pun(?) intended). But I just had to try on this one... There is no such thing as "a pointer" -- the pointer (*) syntax is a *constructor*, producing a new and exciting object each time it is used! That is, there is one type "pointer to char" which is ALWAYS a certain size, and which always behaves exactly the same under the defined arithmetic operations... there's another type "pointer to long" that is also self-consistent: but it admittedly does not behave the same as a "pointer to char", and there's no reason why it should. (Are the two arrays (int a1[10]) and (int a2[5]) the same size?) It really is important that pointers and offsets not be confused; it is also important that offsets and integers not be confused -- even though they're kind of the same. (I'm not really sure what I mean by that, except that an integer -- e.g. 5 -- when used in an operation with a pointer should not be viewed as an integer but as an offset, which has "units"; that is, not "five" but "five of those"). As people have said here already, don't think of a pointer as a certain bit-pattern, and incrementing like integer addition. (Get a hold of a PDP-10, or it's assembly manual, and look at byte pointers instructions to modify them -- it'll cure you in a hurry.) Rather than agree/disagree on the merits of earlier arguments presented, how about a plea for peace: there was a statement about pointers not having "units". Let's pretend they do, but we don't know what to call them -- and that you certainly can add to pointers but the thing you get is different units, and there's no other operations defined on them, so who care? (Maybe look at pointers as logs? I can add and subtract them and I know how to use the result for multiplication and division. I can also mulitply them, but I don't know what to do with the result. [Note the *I*, not *you*, since there's sure to be some *you* out there just dying to explain about products of logarithms. Direct those followups to sci.math where I won't have to read them :-] ) --Jeremy Siegel 3Com Corp. Mountain View
scs@sloth.pika.mit.edu (Steve Summit) (05/11/89)
I think everybody has figured out by now why pointer addition doesn't work or make sense, but I'll throw in another perspective just for good measure. I think Blair's original confusion stemmed from wanting to treat a pointer as an actual memory address. It's true that pointers are represented on many if not most machines by actual memory addresses, and that pointers are generated with the "&" operator which is named "address of", and that thinking about machine addresses is often a helpful way to think about pointers; but as has been amply pointed out, a pointer is properly a higher-level language construct which is removed from, and insulates the programmer from the details of, the implementation. The one time I wanted to add pointers was when writing a dynamic linker. It seems reasonable, at first, to use pointers to describe the addresses (locations) of the symbols within an object module being read in. (I'm already groping though; I talked about pointers as addresses because that's how they're usually implemented; now I'm turning around and trying to implement an address as a pointer as if they were the same.) Additionally, I may well have a pointer (call it "base") to the spot in memory into which the object module is being dynamically read. One of the things a linker must do is relocation. Suppose an object module defines a symbol x, and that the symbol's address/location is 4 (relative to the beginning of the object module; that is, the object module essentially defines a frame of reference that assumes that the module begins at location/address 0.) If I am using a pointer as my generic address type, I might read the "4" out of the object module's symbol table and cram it (via any suitable means) into a variable (call it "loc") of pointer type. Once the object module is read in, the actual address/location in memory of the symbol x will be base + loc (x was at "loc" relative to the start of the module, which is being read in at address/location "base"). So, if I had declared both base and loc as pointers, the compiler would have complained when I tried to compute base + loc. (In fact, that is how I did attempt to write it, at first; and in figuring out why it couldn't work, I gained a deeper understanding of the relationship, and differences, between pointers and addresses, which is what I am trying to impart here.) The problem is that, in writing a linker, I have dropped completely beneath the machine-independent high-level abstract model which the language provides. What I eventually did was to represent addresses/locations as unsigned integers, no longer attempting to disguise the fact that I was, in fact, dealing with actual machine addresses, which are (for a flat-address machine) honest-to-God numbers, not pointers. On a non-flat-address space machine, the appropriate type for a machine address may be some semi-complicated structure, and computing base + loc might require a subroutine call (which C++ could hide for me...) to a routine which knew about the memory model of the machine in use. Obviously, such code is unportable, but code which gets real close to the machine (assemblers, linkers, debuggers, kernels) does tend to have its nonportable aspects. (Don't lose heart, though; they can also have their portable aspects.) The moral is, if you want (and have good reason) to talk about actual machine addresses, don't beat around the bush with pointers. Use integers or structures or whatever you have to use to accurately describe the machine addresses you're actually using. Steve Summit scs@adam.pika.mit.edu
throopw@dg-rtp.dg.com (Wayne A. Throop) (05/13/89)
> bph@buengc.BU.EDU (Blair P. Houghton) >>The point is, Blair expects an object defined as one type to behave both >>as if it were a pointer and an offset at the same time. This is NOT sensible. > Nay, I want it to behave as an object, and not as some nebulous changeling > requiring maintenance-by-fiat. If one is yea-big and the other is yo-big, > then I damn well want the difference between them to be yea-yo, at the > very least when I _tell_ it to be so. > It's sensible aplenty. "Nebulous changeling"? "Yea-big"? "Yo-big"? This is *sensible*? I'm guessing here, but I suppose that Blair is being flip. But I have no idea whatsoever why the rather clear-cut, simple and elegant semantics that C has assigned to pointer arithmetic should be characterized as "nebulous". Pointers DO behave as objects, so I don't know why Blair makes special mention that he wishes they did behave so. And finally, several people have pointed out why a single object representing both position and offset is not a good idea, so I have NO idea what all this yea-yo stuff is about.... maybe it's a bilingual joke I don't get, a takeoff on "viva yo" or "yeah me" or something. A show of hands here. How many think a pointer in c doesn't "behave as an object"? Yeah, I thought so... -- "You'd be surprised... they're all separate little countries down there." --- Ronald Wilson Reagan Wayne Throop <the-known-world>!mcnc!rti!xyzzy!throopw