dkonerding@eagle.wesleyan.edu (08/12/89)
Hi folks. I'm a confused beginner C programmer who'd like to understand pointer variables a bit better. I have a small program. I've done the following: int *ptr; Now, say I make ptr=1000 or hex 3e8. I want to add one to the ptr, to make it point to 1001, or hex 3e9. Every time I do a ptr=ptr+1, it becomes 3ec. How can I simply increment ptr by one?
gwyn@smoke.BRL.MIL (Doug Gwyn) (08/12/89)
In article <484@eagle.wesleyan.edu> dkonerding@eagle.wesleyan.edu writes: > int *ptr; > Now, say I make ptr=1000 or hex 3e8. I want to add one to the ptr, to >make it point to 1001, or hex 3e9. Every time I do a ptr=ptr+1, it becomes >3ec. How can I simply increment ptr by one? Wu! (If you're not familiar with Zen: that means you should unask your question.) C pointers are more abstract than machine storage addresses, and once you properly grok them (look up "grok" in "Stranger in a Strange Land"), they more naturally lend themselves to expressing object reference than raw untyped addresses would. If you're having to fight them, it's probably a sign that you need to improve your understanding of them. Except under extremely unusual circumstances, which as a C beginner you are probably not faced with, proper use of pointers REQUIRES that you not even consider what "numerical values" they are supposed to have. If you have a pointer to one of a contiguous series (i.e. an array) of data each of which has type int, and you wish to make the pointer point at the next member of the array, express that by "adding one" to the pointer. The meaning of "adding N" to a pointer-to-a-whatever is to produce a pointer-to-the-whatever-N- whatevers-farther-along-the-array. Forget about machine address arithmetic; of course there must be some going on behind the scenes, but you're not supposed to consider how it's accomplished. If you wish to access individual members of an array of bytes, use a pointer-to-char instead of pointer-to-int. In C, a char is a byte. (A byte need not be 8 bits, although that is the size most commonly encountered.) If, instead of dealing with nice, regular arrays, you're really trying to access a "misaligned" int datum using a pointer to an aligned int as a starting point, then you need to convert the original pointer-to-int to a pointer-to-char (-byte) to do the bytewise pointer arithmetic, then convert it back again afterward. This series of operations cannot be made to work on some computer architectures. (It is expressed by ptr = (int*)((char*)ptr + 1); /* NON-PORTABLE */ which does as I just said.) Be sure that you really need to do this; in many years of varied C programming I've rarely needed to do anything like that.
john@chinet.chi.il.us (John Mundt) (08/12/89)
In article <484@eagle.wesleyan.edu> dkonerding@eagle.wesleyan.edu writes: > > Hi folks. I'm a confused beginner C programmer who'd like to >understand pointer variables a bit better. I have a small program. I've done >the following: int *ptr; > > Now, say I make ptr=1000 or hex 3e8. I want to add one to the ptr, to >make it point to 1001, or hex 3e9. Every time I do a ptr=ptr+1, it becomes >3ec. How can I simply increment ptr by one? It is doing exactly what K & R want it to do. When you do pointer arithmetic, your addition is scaled by the size of the object the ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ pointer points to. You must have a 4 byte int on the machine you are using, since making ptr one larger caused it to point to the next int. For example, if you had an array of pointers starting at memory location 1000, you'd have this: 1000+ 0 4 8 12 16 20 24 28 32 36 40 44 48 52 56 |---|---|---|---|---|---|---|---|---|---|---|---|---|---| 1st 2nd 3rd 4th 5th 6th 7th 8th 9th etc *ptr would have the value held at 1000, *(ptr + 1) would hold the value at 1004, *(ptr+2) the value at 1008, etc. If you had made ptr a pointer to char, as in char *ptr; then doing ptr = ptr + 1; would give you 1001, since the size of a char is one byte. Alternatively, if pointer was a pointer to a structure struct foo { /* this structure is 40 bytes long */ char foo1[20]; char foo2[20]; } ary[2]; struct foo *ptr = &ary[0]; /* make ptr point to first ary */ /* which we will assume as at 1000 again */ then ptr = ptr + 1 would equal 1040, since stepping ptr by one moves it from the first structure to the second, which is what we want to do. -- --------------------- John Mundt Teachers' Aide, Inc. P.O. Box 1666 Highland Park, IL john@chinet.chi.il.us (312) 998-5007 (Day voice) || -432-8860 (Answer Mach) && -432-5386 Modem
cpcahil@virtech.UUCP (Conor P. Cahill) (08/12/89)
In article <484@eagle.wesleyan.edu>, dkonerding@eagle.wesleyan.edu writes: > Now, say I make ptr=1000 or hex 3e8. I want to add one to the ptr, to > make it point to 1001, or hex 3e9. Every time I do a ptr=ptr+1, it becomes > 3ec. How can I simply increment ptr by one? By declaring the pointer as char * ptr; an increment of a pointer moves the pointer to the next occurance of the item to which it points to. In your case I am assuming an integer is 4 bytes and the compiler correctly moved the pointer to point to the next integer that ptr may point to. This goes the same for structures.
brian@trantext.UUCP (Brian Bainter) (08/13/89)
In article <484@eagle.wesleyan.edu>, dkonerding@eagle.wesleyan.edu writes: > > Hi folks. I'm a confused beginner C programmer who'd like to > understand pointer variables a bit better. I have a small program. I've done > the following: int *ptr; > > Now, say I make ptr=1000 or hex 3e8. I want to add one to the ptr, to > make it point to 1001, or hex 3e9. Every time I do a ptr=ptr+1, it becomes > 3ec. How can I simply increment ptr by one? You must realize what you are incrementing here. Since you are working with an integer pointer here, you are incrementing the pointer to the next integer. Since you seem to be working on a machine where integers are equivalent in size to longs, your incrementation (is that a word?) of the pointer will place you four bytes down the road (at the next integer position). If you want a pointer to increment to the next byte, you must use a character pointer of type "char *". Since character arrays are built on one byte increments, incrementing a character pointer will place the pointer at the next byte or character position. The same holds true with any kind of pointer. If you have a pointer to a structure of say 35 bytes, every time you increment the pointer, it will point to the next structure of 35 bytes (unless you are working on a CPU similar to the 68x00 family where odd word boundaries are not allowed which may place each structure every 36 bytes apart). The main thing to remember with pointer arithmetic is what type of variable am I pointing to and how much memory does that variable take up, and when I increment a pointer to that variable I will be incrementing the pointer by the number of bytes the variable takes up times the number I am adding to the pointer. The same holds true with I believe any arithmetic operation done on a pointer (add, subtract, multiply, devide, etc.). Hope this helps, -- Brian R. Bainter KA7TXA gatech!kd4nc!trantext!brian or gatech!tomcat!brian
ping@cubmol.BIO.COLUMBIA.EDU (Shiping Zhang) (08/13/89)
In article <484@eagle.wesleyan.edu> dkonerding@eagle.wesleyan.edu writes: > > Hi folks. I'm a confused beginner C programmer who'd like to >understand pointer variables a bit better. I have a small program. I've done >the following: int *ptr; > > Now, say I make ptr=1000 or hex 3e8. I want to add one to the ptr, to >make it point to 1001, or hex 3e9. Every time I do a ptr=ptr+1, it becomes >3ec. How can I simply increment ptr by one? Points hold the locations or addresses of the varibles they point to. So they change in units of the size (in bytes) of the varible type they point to. On most of machines, the int size is 4 (bytes,or 32 bits). So increasing a point to int by 1 advances the point to the address of the next int, which is 4 bytes further, therefore the value of the point is increased by 4. -ping
gwyn@smoke.BRL.MIL (Doug Gwyn) (08/13/89)
In article <10717@smoke.BRL.MIL>, gwyn@smoke.BRL.MIL (Doug Gwyn) writes: > Wu! (If you're not familiar with Zen: that means you should unask your > question.) Of course I meant "Mu!". Another in a continuing series of misfiring neurons in my memory circuits.. The proclaimed "meaning" given above has been challenged. I don't claim to be a Zen expert and may have misunderstood the koan that this relates to. On the other hand, Zen can't really be understood, so who knows. I have no idea where followups on this topic should go. (Probably there shouldn't be any!)
wolfgang@ruso.UUCP (Wolfgang Deifel) (08/15/89)
dkonerding@eagle.wesleyan.edu writes: >... int *ptr; > Now, say I make ptr=1000 or hex 3e8. I want to add one to the ptr, to >make it point to 1001, or hex 3e9. Every time I do a ptr=ptr+1, it becomes >3ec. How can I simply increment ptr by one? ptr is a pointer to an int or array of ints. When you add 1 or increment ptr it always refers to the next element e.g. it becomes sizeof(*ptr) more. If you want to increment ptr only by one you should use a cast. ((char*)ptr)++ ; or ((char*)ptr) + 1 ; Now ptr becomes 1 ( = sizeof(char) ) more. ---------------------------------------------------------------------------- Wolfgang Deifel Dr. Ruff Software GmbH, 5100 Aachen, Juelicherstr. 65-67, W-Germany uucp: ...!uunet{!mcvax}!unido!rwthinf!ruso!wolfgang - phone : +49 241 156038
chris@mimsy.UUCP (Chris Torek) (08/16/89)
In article <829@ruso.UUCP> wolfgang@ruso.UUCP (Wolfgang Deifel) writes: >If you want to increment ptr only by one [byte] you should use a cast. > > ((char*)ptr)++ ; >or > ((char*)ptr) + 1 ; The former is illegal: the result of a cast is an rvalue (thing that goes on the right of an `=' sign), not an lvalue (thing that goes on the left). ++ may only be applied to lvalues. Many compilers simply got this wrong; at least one (gcc) allows it as an `extension', although it is not clear to me what gcc might do with it on a machine in the DG MV series, where a cast from (int *) to (char *) generates a shift-and-mask sequence (possibly an efficient one; this one is for demonstration purposes): /* char *cp; int *ip; cp = (char *)ip; more(); */ load reg1,-4(frame) // fetch ip lsh #1,reg1 // shift it left store reg1,-8(frame) // and store in ip call more_ Perhaps on such a machine, gcc might compile `((char *)ip)++' as load reg1,-4(frame) // fetch ip lsh #1,reg1 // shift it left call more_ thus incrementing a temporary by one and then discarding the result. (If gcc maps `((cast)(lvalue))++' internally to `{temp = lvalue; lvalue = (cast)lvalue + 1; resultis temp;}', it would do something a bit more reasonable---in the example I am thinking of, it would result in incrementing the word-pointer ip by zero. Word-pointers on many machines simply cannot point to a byte within a word. The byte number, carried around in character pointers, is irrelevant to the machine instructions that deal with words, and must be discarded ---in this example, by shifting right one bit.) -- In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 7163) Domain: chris@mimsy.umd.edu Path: uunet!mimsy!chris
maart@cs.vu.nl (Maarten Litmaath) (08/16/89)
wolfgang@ruso.UUCP (Wolfgang Deifel) writes:
\...
\ ((char*)ptr)++ ;
\or
\ ((char*)ptr) + 1 ;
\
\Now ptr becomes 1 ( = sizeof(char) ) more.
Aaaaaaarrrrrgghh! Wayne Throop's Sacred Mission isn't finished yet...
--
"Mom! Eric Newton broke the day! In 24 |Maarten Litmaath @ VU Amsterdam:
parts!" (Mike Schmitt in misc.misc) |maart@cs.vu.nl, mcvax!botter!maart
karzes@mfci.UUCP (Tom Karzes) (08/17/89)
In article <829@ruso.UUCP> wolfgang@ruso.UUCP (Wolfgang Deifel) writes: >dkonerding@eagle.wesleyan.edu writes: >If you want to increment ptr only by one you should use a cast. > > ((char*)ptr)++ ; This is not legal C, since a cast expression is not a valid LHS. You can no more use this than you can use: ((char *) ptr) = ...; Some compilers may accept this, but it isn't legal C.
wolfgang@ruso.UUCP (Wolfgang Deifel) (08/18/89)
maart@cs.vu.nl (Maarten Litmaath) writes: > I wrote: >\... >\ ((char*)ptr)++ ; >\Now ptr becomes 1 ( = sizeof(char) ) more. >Aaaaaaarrrrrgghh! Wayne Throop's Sacred Mission isn't finished yet... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Thank god that you are born as expert...
maart@cs.vu.nl (Maarten Litmaath) (08/22/89)
wolfgang@ruso.UUCP (Wolfgang Deifel) writes: \maart@cs.vu.nl (Maarten Litmaath) writes: \> I wrote: \>\... \>\ ((char*)ptr)++ ; \>\Now ptr becomes 1 ( = sizeof(char) ) more. \ \>Aaaaaaarrrrrgghh! Wayne Throop's Sacred Mission isn't finished yet... \ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ \ \ Thank god that you are born as expert... There's no need to feel p*ssed off, Wolfgang; I wasn't trying to insult you or something. Of course I should have added a detailed explanation, but I figured someone else would supply that. Having read your article I remembered Wayne Throop's 1985 (1986?) crusade against "the vile heresy which claimeth that ((char*)ptr)++ will increment ptr" (free after Henry Spencer's Ten Commandments for C Programmers). Allright. A compiler that allows the abovementioned construct is wrong for two reasons: 1) It allows the `++' operator to be applied to an Rvalue expression; only Lvalue expressions may be operand of an increment operator, e.g. x++ a[i]++ This isn't so strange: x++ is equivalent to x = x + 1 which doesn't make sense for arbitrary (Rvalue) expressions. 2) It increments the wrong variable; a cast is equivalent to an assignment to an invisible temporary variable (with the usual restrictions and conversions): foo x; ... (bar) x ... becomes foo x; bar cast_tmp; /* `invisible' temp variable */ ... (cast_tmp = x) ... If we write the latter expression as (cast_tmp = x, cast_tmp) it's clearly `cast_tmp' which should be incremented (if a `++' operator is appended), were this possible at all; definitely NOT `x'. -- "rot H - dD/dt = J, div D = rho, div B = 0, |Maarten Litmaath @ VU Amsterdam: rot E + dB/dt = 0" and there was light. |maart@cs.vu.nl, mcvax!botter!maart