Quote:
> How do pointers to int differ from pointers to char?
They are meant to point to objects of different sizes (sizeof(int) and
sizeof(char)) and properties. However compilers often take your word for
it that an int pointer really points to an int, and that a char pointer
really points to a char. They do this because they have no way to verify
what pointers really point to. So you have to be careful that what they
point to matches what they say they do (or that you really know what
you're doing when they don't).
Quote:
> Thanks!!
The following is in an 'as if' vein - what I describe may not actually
happen in any particular real environment, but any real environment
behaves more-or-less 'as if' this happens.
Quote:
> ---- wacky3.c -----
> #include <stdio.h>
> main()
> {
> char *c;
> char d[] = "This is the real test, ok";
> c = "This is a test, ok.";
This creates, somewhere in memory, a char pointer 'c', a character array
'd', and an anonymous string 'This is a test, ok'.
'c' is initialized to the address of the character 'T' at the start of
the anonymous string. 'd' is initialized to the value 'This is the real
test, ok'.
Quote:
> printf("c is: %s\n", c);
This creates, somewhere in memory, another anonymous string 'c is:
%s\n'. The compiler creates code that pushes the address of this string
and the contents of 'c' (the address of 'T') on the stack, then calls
printf().
When executed, printf() recovers the address of the format string and
looks through it. When it finds the '%s' specifier, it pulls the next
item off the stack, interprets it as the starting address of a
null-terminated string, and prints whatever it finds there.
Ok so far.
Quote:
> printf("&c is: %d\n", &c);
Another anonymous string, etc., except that this time the address of 'c'
itself, rather than the address of 'T', is pushed on the stack.
When printf() sees the '%d' specified, it interprets the next item on
the stack as an integer and prints it. What is actually on the stack is
the address of a variable, which doesn't necessarily have to be
representable as an integer. In this case it probably works - but it
doesn't have to.
Quote:
> printf("*c: %s\n", *c);
Another anonymous string, etc., except that this time the character 'T'
is pushed on the stack.
When printf() sees the '%s' specifier, it pulls an address off the
stack. What is actually on the stack is a character, which is an object
that is most likely smaller than an address. So 'T' and a few random
bytes are used as the starting address of a null-terminated string, and
printf() shows whatever it finds there (aren't you glad it found a null
byte so soon?).
This happened because *you* told printf() that the character 'T' was the
address of a null-terminated string, and it believed you.
Quote:
> c = "crud";
Another anonymous string, 'crud', is created and 'c' is reset to point
to the initial letter 'c'.
Quote:
> printf("c is: %s\n", c);
> printf("&c is: %d\n", &c);
> printf("*c: %s\n", *c);
As before, except that the character 'c' interpreted as an address
doesn't seem to lead to printable output. Oh well, that's what they
mean by 'undefined' - you don't know what you'll get.
Quote:
> c = &d;
'c' is reset to point to d[0], which currently holds the character 'T'.
Quote:
> printf("c is: %s\n", c);
> printf("&c is: %d\n", &c);
> printf("*c: %s\n", *c);
As before. 'Undefined' doesn't necessarily mean 'unrepeatable'. It seems
to be the case that the letter 'T' interpreted as an address happens to
lead to the same output as it did the first time (but it needn't
necessarily do so, and probably wouldn't have if anything at that
address had changed in the interim).
Quote:
> return 0;
> }
> ----- end wacky3.c -----
> ----- wacky4.c -----
> #include <stdio.h>
> main()
> {
> int *p;
> int q;
> q = 13;
> p = &q;
This creates, somewhere in memory, the integer pointer 'p' and the
integer 'q'.
'p' is initialized to the address of 'q'. 'q' is initialized to the
value '13'.
Quote:
> printf("q is: %d\n", q);
As before, except that the value held in 'q' ('13') is pushed on the
stack. printf() displays it just fine.
Quote:
> printf("&q is: %d\n\n", &q);
As before.
Quote:
> printf("p is: %d\n", p);
As before, except that the value held in 'p' happens to be the address
of 'q'. So this printf() displays the same value the last printf() did.
Quote:
> printf("*p is: %d\n", *p);
As before, except that '*p' results in the value '13' being pushed on
the stack. That is, the integer value ('13') at the address held in 'p'
('q'). All works as expected.
But printf() would have displayed *some* integer value no matter what
value 'p' contained, even if you never initialized it. The expression
'*p' interprets whatever 'p' happens to contain as an address, and
whatever is actually at that address is interpreted as an integer. If
either of those assumptions happens to be untrue at the time the
expression is evaluated, you get something, but most likely not what
you're expecting.
So here's another way to go wrong: initialize 'p' to the address of 'q',
but never initialize 'q'. You get whatever random bytes 'q' holds,
interpreted as an integer.
Quote:
> printf("&p is: %d\n", &p);
As before.
Quote:
Hope this helps.
- Anton
Quote:
> ----- end wacky4.c -----
> OK, so now lets run these programs:
> ----- begin execution -----
> c:\e\c_prog~1>gcc -o wacky3 wacky3.c
> wacky3.c: In function `main':
> wacky3.c:20: warning: assignment from incompatible pointer type
> c:\e\c_prog~1>wacky3
> c is: This is a test, ok.
> &c is: 308872
> *c: -a= ?
> c is: crud
> &c is: 308872
> *c:
> c is: This is the real test, ok
> &c is: 308872
> *c: -a= ?
> c:\e\c_prog~1>wacky4
> q is: 13
> &q is: 308868
> p is: 308868
> *p is: 13
> &p is: 308872
> ----- end execution -----
> --
--