char pointers vs. int pointers 
Author Message
 char pointers vs. int pointers

Hi folks, I've read the faq and couldn't seem to figure out what's going on
here, so someone please put me out of my misery.  I've *never* 100%
understood pointers.  Anyway, here's the problem (some short source code
follows to illustrate my point):

Ok, so now if you've looked at the source code, my question is, why does
wacky4.c behave as I expect, that is, *c contains the value of the variable
you want e.g. 13, but in wacky3.c, c contains the value of the variable you
want e.g. "This is a test, ok", but *c contains rubbish?

How do pointers to int differ from pointers to char?

Thanks!!

ps. if you haven't already explained it, why did I get a compiler warning
for wacky3.c?

--
Ashley Smith

---- wacky3.c -----
#include <stdio.h>

main()
{
        char *c;
        char d[] = "This is the real test, ok";
        c = "This is a test, ok.";

        printf("c is:        %s\n", c);
        printf("&c is:       %d\n", &c);
        printf("*c:          %s\n", *c);

        c = "crud";

        printf("c is:        %s\n", c);
        printf("&c is:       %d\n", &c);
        printf("*c:          %s\n", *c);

        c = &d;

        printf("c is:        %s\n", c);
        printf("&c is:       %d\n", &c);
        printf("*c:          %s\n", *c);

        return 0;

Quote:
}

----- end wacky3.c -----

----- wacky4.c -----
#include <stdio.h>

main()
{
        int *p;
        int q;
        q = 13;
        p = &q;

        printf("q is:           %d\n", q);
        printf("&q is:          %d\n\n", &q);
        printf("p is:           %d\n", p);
        printf("*p is:          %d\n", *p);
        printf("&p is:          %d\n", &p);

        return 0;

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 -----

--



Tue, 29 Jan 2002 03:00:00 GMT  
 char pointers vs. int pointers
On Fri, 13 Aug 1999 20:03:43 GMT, "Ashley Smith"

Quote:
> Hi folks, I've read the faq and couldn't seem to figure out what's going on
> here, so someone please put me out of my misery.  I've *never* 100%
> understood pointers.  Anyway, here's the problem (some short source code
> follows to illustrate my point):

> Ok, so now if you've looked at the source code, my question is, why does
> wacky4.c behave as I expect, that is, *c contains the value of the variable
> you want e.g. 13, but in wacky3.c, c contains the value of the variable you
> want e.g. "This is a test, ok", but *c contains rubbish?

> How do pointers to int differ from pointers to char?

> Thanks!!

> ps. if you haven't already explained it, why did I get a compiler warning
> for wacky3.c?

> --
> Ashley Smith

> ---- wacky3.c -----
> #include <stdio.h>

> main()

Better make this int main(), or even better int main(void), implicit
int is going to become illegal soon.

Quote:
> {
>         char *c;
>         char d[] = "This is the real test, ok";
>         c = "This is a test, ok.";

>         printf("c is:        %s\n", c);
>         printf("&c is:       %d\n", &c);

The line above is illegal now, and produces undefined behavior because
you pass a pointer to printf with a "%d" conversion specifier.  This
should be:

printf("&c is:  %p\n", (void *)&c);

The "%p" is the only legal conversion specifier for a pointer and
requires a void pointer argument, hence the cast.

Quote:
>         printf("*c:          %s\n", *c);

c is a pointer to char, and also a pointer to a string if it points to
a char containing the value '\0' or an array of chars terminated with
'\0'.  *c is a single char, not a pointer to a string so you should
not print it with "%s".  To print a single char you need to use "%c".

Quote:
>         c = "crud";

>         printf("c is:        %s\n", c);
>         printf("&c is:       %d\n", &c);
>         printf("*c:          %s\n", *c);

>         c = &d;

d is an array of chars, c is a pointer to char.  &d has the type
"pointer to array of char", not the type "pointer to char".  When you
assign an array by name to a pointer the array name decays into a
pointer to its first element.

Correct the line by using either:

c = d; or c = &d[0];

- Show quoted text -

Quote:

>         printf("c is:        %s\n", c);
>         printf("&c is:       %d\n", &c);
>         printf("*c:          %s\n", *c);

>         return 0;
> }
> ----- end wacky3.c -----

> ----- wacky4.c -----
> #include <stdio.h>

> main()
> {
>         int *p;
>         int q;
>         q = 13;
>         p = &q;

>         printf("q is:           %d\n", q);
>         printf("&q is:          %d\n\n", &q);

Again, printf("&q is: %p\n", (void *)&q);

Quote:
>         printf("p is:           %d\n", p);

Same here, you are printing the value held in p, which is a pointer:

printf("p is:  %p\n", (void *)p;

Quote:
>         printf("*p is:          %d\n", *p);

This one is OK, p is a (properly initialized) pointer to int, so *p is
an int and printing with "%d" is correct.

Quote:
>         printf("&p is:          %d\n", &p);

Again use %p and cast to pointer to void.

Quote:

>         return 0;
> }
> ----- 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.

Printed a string, OK.

Quote:
> &c is:       308872

You are lucky that printf() made something sensible out of this.
Again printing a pointer or address value with "%d" is just plain
undefined behavior.

Quote:
> *c:          -a= ?

This is where you told printf() to print *c (a char) using a "%s"
which is a conversion specifier for pointer to char.  So printf() took
the numeric value of *c (in this case 'T') and tries to dereference it
to find a string there.  On many operating systems your program would
be shut down with a memory protection error on the spot.

Quote:
> 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 -----

The mistake you are asking about is using "%s" instead of "%c" to
print *c which is a single char.  But note that your method of passing
pointers to printf() with "%d" is a bug and just happens not to crash
or do something else {*filter*} by accident on your implementation.

Jack Klein
--
Home: http://www.*-*-*.com/ ~jackklein
--



Wed, 30 Jan 2002 03:00:00 GMT  
 char pointers vs. int pointers


Quote:
>How do pointers to int differ from pointers to char?

Well among other things, pointers to char are given a special
significance in C in so far as they can be 'strings'.  Another feature
is that char * must be 'the same' as void * and so must be 'large
enough' to store the information content of any pointer.  Note that this
means that on some systems sizeof(char*) > sizeof(int *)

Francis Glassborow      Journal Editor, Association of C & C++ Users
64 Southfield Rd
Oxford OX4 1PA          +44(0)1865 246490
All opinions are mine and do not represent those of any organisation
--



Wed, 30 Jan 2002 03:00:00 GMT  
 char pointers vs. int pointers

Quote:

> Hi folks, I've read the faq and couldn't seem to figure out what's going on
> here, so someone please put me out of my misery.  I've *never* 100%
> understood pointers.  Anyway, here's the problem (some short source code
> follows to illustrate my point):

> Ok, so now if you've looked at the source code, my question is, why does
> wacky4.c behave as I expect, that is, *c contains the value of the variable
> you want e.g. 13, but in wacky3.c, c contains the value of the variable you
> want e.g. "This is a test, ok", but *c contains rubbish?

Both wacky3.c and wacky4.c have  a number of mistakes.  See if the
following rewrite helps your understanding any.  Feel free to ask
followup questions to anything that puzzles you.

#include <stdio.h>

int wacky3(void)
{
    const char *c;              /* mha - added const, since you will
                                   point to a string that may not be
                                   modifiable */
    char d[] = "This is the real test, ok";
    c = "This is a test, ok.";

    printf("c is:        %s\n", c);
#if 0
    printf("&c is:       %d\n", &c);
    printf("*c:          %s\n", *c);
#endif
    printf("c is:        %p\n", (void *)c);     /* mha - replacement */
    printf("*c:          %c\n", *c);    /* mha - replacement */

    c = "crud";

    printf("c is:        %s\n", c);
#if 0
    printf("&c is:       %d\n", &c);
    printf("*c:          %s\n", *c);
#endif
    printf("c is:        %p\n", (void *)c);     /* mha - replacement */
    printf("*c:          %c\n", *c);    /* mha - replacement */

#if 0
    c = &d;
#endif
    c = d;                      /* mha - replacement */

    printf("c is:        %s\n", c);
#if 0
    printf("&c is:       %d\n", &c);
    printf("*c:          %s\n", *c);
#endif
    printf("c is:        %p\n", (void *)c);     /* mha - replacement */
    printf("*c:          %c\n", *c);    /* mha - replacement */

    return 0;

Quote:
}

int wacky4(void)
{
    int *p;
    int q;
    q = 13;
    p = &q;

    printf("q is:           %d\n", q);
#if 0
    printf("&q is:          %d\n\n", &q);
    printf("p is:           %d\n", p);
#endif
    printf("&q is:          %p\n\n", (void *)&q);   /* mha -
                                                       replacement */
    printf("p is:           %p\n", (void *)p);  /* mha - replacement */

    printf("*p is:          %d\n", *p);
#if 0
    printf("&p is:          %d\n", &p);
#endif
    printf("p is:           %p\n", (void *)p);  /* mha */
    printf("&p is:          %p\n", (void *)&p);     /* mha */
    return 0;

Quote:
}

int main(void)
{
    printf("Running wacky3 ... \n");
    wacky3();
    printf("Running wacky4 ... \n");
    wacky4();
    return 0;

Quote:
}

/* vi: set cindent ts=4 sw=4 et tw=72: */

Quote:
> How do pointers to int differ from pointers to char?

> Thanks!!

> ps. if you haven't already explained it, why did I get a compiler warning
> for wacky3.c?

> --
> Ashley Smith

> ---- wacky3.c -----
> #include <stdio.h>

> main()
> {
>         char *c;
>         char d[] = "This is the real test, ok";
>         c = "This is a test, ok.";

>         printf("c is:        %s\n", c);
>         printf("&c is:       %d\n", &c);
>         printf("*c:          %s\n", *c);

>         c = "crud";

>         printf("c is:        %s\n", c);
>         printf("&c is:       %d\n", &c);
>         printf("*c:          %s\n", *c);

>         c = &d;

>         printf("c is:        %s\n", c);
>         printf("&c is:       %d\n", &c);
>         printf("*c:          %s\n", *c);

>         return 0;
> }
> ----- end wacky3.c -----

> ----- wacky4.c -----
> #include <stdio.h>

> main()
> {
>         int *p;
>         int q;
>         q = 13;
>         p = &q;

>         printf("q is:           %d\n", q);
>         printf("&q is:          %d\n\n", &q);
>         printf("p is:           %d\n", p);
>         printf("*p is:          %d\n", *p);
>         printf("&p is:          %d\n", &p);

>         return 0;
> }
> ----- 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 -----

> --


--

__________________________________________________________
Fight spam now!
Get your free anti-spam service: http://www.brightmail.com
--



Thu, 31 Jan 2002 03:00:00 GMT  
 char pointers vs. int pointers

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:

>         return 0;
> }

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 -----

> --


--



Thu, 31 Jan 2002 03:00:00 GMT  
 
 [ 5 post ] 

 Relevant Pages 

1. A char pointer (char *) vs. char array question

2. arrays and pointers, char * vs. char [], distinction

3. Comparison with pointer to pointer to char, and char

4. Help with pointers, and char -> int

5. Casting between int and pointer to char

6. convert char to short int via pointer?...

7. pointer alignment when int != char *

8. int Pointer and struct pointer

9. dereferencing pointer to a structure containing a pointer to int

10. pointer to pointer to int

11. Pointer arithmetic: char* vs. void*

12. array declaration vs. char pointer

 

 
Powered by phpBB® Forum Software