Pointer question...last for the day? :-)

M

mdh

One thing has puzzled me a while ( well, more than one thing!).

If I have a function:

foo( char *s){

char *t = s;

......


s++; <<--- a few arbitrary times

}

Now...my question is this.

Is "t" independent of s, in the sense of:

1) Will it still point to the beginning of s, after s++ ?

2) I guess related to 1, if I now evaluate *t, will it be the first
character in s?

Thanks...that's it for today!!!
 
R

Robert Gamble

One thing has puzzled me a while ( well, more than one thing!).

If I have a function:

foo( char *s){

char *t = s;

.....

s++; <<--- a few arbitrary times

}

Now...my question is this.

Is "t" independent of s, in the sense of:

1) Will it still point to the beginning of s, after s++ ?

2) I guess related to 1, if I now evaluate *t, will it be the first
character in s?

Thanks...that's it for today!!!

How long does something have to puzzle you before you give it a try
and see what happens?
 
M

mdh

Of course.

For some reason I had this conceptual notion that as s is incremented,
it causes t to "see" the same part of the original array as s. What
you are saying is that once the new pointer is initialized, it acts
independently and can be used as such?
 
R

Robert Gamble

For some reason I had this conceptual notion that as s is incremented,
it causes t to "see" the same part of the original array as s. What
you are saying is that once the new pointer is initialized, it acts
independently and can be used as such?

s and t are distinct objects, both of which point to the same place
initially, for example, say they both point to the string "abc":

s
|
V
+-+-+-+--+
|a|b|c|\0|
+-+-+-+--+
^
|
t

After you execute s++, s points to the next character in the string:

s
|
V
+-+-+-+--+
|a|b|c|\0|
+-+-+-+--+
^
|
t

but t is unchanged. If you modify the data that s points to, i.e.
*s='e' :

s
|
V
+-+-+-+--+
|a|e|c|\0|
+-+-+-+--+
^
|
t

and then access the data through t you will see "aec" since they both
point into the same, now modified, object.
 
M

mdh

A pointer in C is just a can to hold an address. Once you shove something
into that can, it does not get changed until you change it.

There are some more mind bending versions of this situation, which may be
what has caused your confusion.


Thanks..it does...

I will leave the mind bending stuff for a little later, but your
example does clarify it!
 
M

mdh

s and t are distinct objects, both of which point to the same place
initially, for example, say they both point to the string "abc":

 s
 |
 V
+-+-+-+--+
|a|b|c|\0|
+-+-+-+--+
 ^
 |
 t

After you execute s++, s points to the next character in the string:

   s
   |
   V
+-+-+-+--+
|a|b|c|\0|
+-+-+-+--+
 ^
 |
 t

but t is unchanged.  If you modify the data that s points to, i.e.
*s='e' :

   s
   |
   V
+-+-+-+--+
|a|e|c|\0|
+-+-+-+--+
 ^
 |
 t

and then access the data through t you will see "aec" since they both
point into the same, now modified, object.


Thanks Robert. These things are so obvious once one understands them.
 
P

Peter Nilsson

Robert said:
...How long does something have to puzzle you before you give
it a try and see what happens?

C is probably the worst language to adopt a 'suck it and see'
attitude. How often have you heard "It works fine on my
machine"?
 
J

James Dow Allen

This may be a very logical question for someone
trying to teach himself C. Some language constructs
can be quite confusing! But I think *most* good C
programmers have familiarity with machine languages(*)
and therefore visualize s and t as separate memory
words, and see "t = s" and "s++" as simple operations
on these memory words. Conceptual problem disappears!!

Some will say "No, no ... C is defined as an abstract
machine described by legalese English" and I'd need
a lawyer to argue with *them*. The simple fact is that
most good C programmers learned C before the lawyers
took over and visualize explicit machine operations
on the machine's memory words.

(* - one needn't actually learn a machine language.
Programming languages that are almost the same as
machine languages are good enough, e.g. Fortran --
whose name means "FORmula TRANslation to machine
language -- or (donning asbestos suit) ... C!!)

BTW, as a minor nit I *detest* the syntax
char *t = s;
which always causes a mental hiccup, due to the misleading
"*". It's simple shorthand for
char *t;
t = s;
Use the less misleading longhand.
How long does something have to puzzle you before you give it a try
and see what happens?

Excellent point and, again, good programmers learn their
trade with experimentation. I was surprised at the
pedantic responses to Mr. Gamble's post. (I love the
*simplicity* of C, but some pedants seem to thrive on
its perceived complexities, perhaps hoping that misleading
novices will improve their own job security.)

The idea that a novice trying to understand
s = t; s++;
shouldn't build his skill by giving
it a try and see what happens
shows confused and laughable thinking.

James Dow Allen
 
R

Rishi

What will happen if it is a integer pointer or an integer array


void foo(char *s,int *x){

int *f=x;
char *k=s;
*f=6;
*k='a';
}


int main(){

int a[5]={1,2,3,4,5};
char *s="hello world";
foo(s,a);
printf("%s %d",s,a[0]);

return 0;
}

output is "hello world 6"

in case of integer the value changed in the function is reflected in
the callee function but in case of characters it is not the case

Why ???
 
T

Tomás Ó hÉilidhe

foo( char *s){

char *t = s;

.....

s++;  <<--- a few arbitrary times

}

Now...my question is this.

Is "t" independent of s, in the sense of:

1) Will it still point to the beginning of s, after s++ ?

2) I guess related to 1, if I now evaluate *t, will it be the first
character in s?


You have to think of things in more concrete terms. There's nothing
magical about a pointer. A pointer stores data, just like any other
kind of variable.

When you want to store data, you have to pick the most suitable data
type.

* If you want to store an integer, use "int"
* If you want to store a floating point number, use "double".
* If you want to store a memory address, use a pointer.

A memory address is a very concrete thing. It's basically a number. It
could 1756, or 345, or 6852.

In your function, let's say that the memory address passed to it is
6852, so the value of s is 6852.

Now you make an object called t, and you give it the value of s. So
now t's value is 6852.

Now you increment s, so s becomes 6853. Then you increment it again to
6854. And again to 6855.

You're changing s, not t. t still keeps the value of 6852.

This is no different from:

void Func(int i)
{
int j = i;

++i;
++i;
++i;

/* j retains the original value of i */
}

Just remember, a pointer holds a memory address, nothing magical.
 
W

Walter Roberson

Rishi said:
void foo(char *s,int *x){
int *f=x;
char *k=s;
*f=6;
*k='a';
}
int main(){
int a[5]={1,2,3,4,5};
char *s="hello world";
foo(s,a);
printf("%s %d",s,a[0]);
return 0;
}

char *s="hello world"; sets the pointer s to be a pointer to a
storage block with program lifetime, and with implementation-defined
semantics as to whether the block is writable or not.

char *s="hello world"; does NOT figure out how big the literal is,
create an array that big, and copy the contents of the literal in:
it sets the pointer to a memory block that already exists.

When you attempt your *k='a' in foo(), you are attempting to write
into the block of memory that is not certain to be writable at all.
If the block doesn't change as a result then the only fault was in
-trying- to change it. And if the block -did- change as a result,
then if you had had any other occurances of "hello world" as a string
literal in your code, those other occurances might have changed as well.

By the way, you did not output a \n at the end of your output.
C doesn't promise that the last line of output will appear at all in that
case. Always ensure you have a terminal \n when outputting to a text
stream.
 
T

Tomás Ó hÉilidhe

void foo(char *s,int *x){

int *f=x;
char *k=s;
*f=6;
*k='a';

}

int main(){

int a[5]={1,2,3,4,5};
char *s="hello world";


There's a quirk in C. The type of a string literal is a non-const
array of char's, even though you're not allowed to modify them.
Stupid, I know.

In your function above which attempts to modify a string literal, you
get a thing known as "undefined behaviour". In the C Standard,
"undefined behaviour" is a cop-out whereby the Standard says "if you
don't follow the rules, then anything can happen, you program may
work, it may not work, I don't care".

In your particular case, on your particular system, the behaviour
which is not defined by the Standard has resulted in nothing
happening. Try changing the code as follows:

char *s = "hello world";

to:

char s[] = "hello world";

Now you should see that your function can change it.
 
K

Keith Thompson

Tomás Ó hÉilidhe said:
A memory address is a very concrete thing. It's basically a number. It
could 1756, or 345, or 6852.
[...]

That's one way to look at it, and it matches the way pointers are
implemented on most systems.

Personally, I prefer to think of pointers (or, equivalently,
addresses) as something a bit more abstract. A pointer value is
something that refers to an object. If the object is an element of an
array, you can perform arithmetic on the pointer value to obtain a
pointer that refers to a different element of the same array. In C,
every pointer value / address has a type associated with it, which
indicates what type of object it can point to.

Pointer values are commonly implemented as numeric machine-level
addresses (usually virtual memory addresses), but that's usually not
the best way to think of them. An address could just as easily be
implemented as a pair of numbers denoting a segment and an offset
within that segment, or as something even more exotic.
 
R

Richard Bos

mdh said:
For some reason I had this conceptual notion that as s is incremented,
it causes t to "see" the same part of the original array as s. What
you are saying is that once the new pointer is initialized, it acts
independently and can be used as such?

Pointers are a lot clearer once you stop thinking of them as something
very special, and start realising that they're just another kind of
object. For example, if you'd done

int s=4;
int t=s;

s++; s++; s++;

I bet you that wouldn't have been at all surprised that s now is 7, but
t still is 4. Well, it's the same for pointers.

Richard
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
474,431
Messages
2,571,679
Members
48,796
Latest member
Greg L.

Latest Threads

Top