C/Pointers

From Attie's Wiki
(Redirected from Pointers)
Jump to: navigation, search

A helper for people starting out with pointers.
For more guidance and words, see Pointers with words

test.c

#include <stdio.h>
#include <stdlib.h>
 
#define P(expr) printf("%10s: 0x%02X\n", #expr, expr)
 
int main(void) {
	char *s = "cba";
	char **p = &s;
 
	P(      s      );
	P(     &s      );
 
	P(      s[0]   );
	P(     *s      );
 
	P(      p      );
	P(     &p      );
	P(      p[0]   );
	P(     *p      );
 
	P(      p[1]   );
 
	P(     *p[1]   ); /* this probably doesn't evaulate to what you think it does... be explicit */
	P(    (*p)[1]  ); /* you probably meant this */
	P(    *(p[1])  ); /* NOT this */
 
	P(    (*p)     );
	P(    (*p)++   ); /* this will modify the s variable */
	P(    (*p)[0]  );
	P(    (*p)     );
	P(  ++(*p)     ); /* this will modify the s variable */
	P(    (*p)[0]  );
	P(    (*p)     );
 
	P(      s      );
 
	return 0;
}

Output

Note the difference between *p[1], (*p)[1] and *(p[1]).

$ gcc test.c -o test && ./test
         s: 0x8048734      <-- the address of the 'c'
        &s: 0xBF893E8C     <-- the address of the variable s
      s[0]: 0x63           <-- the 'c'
        *s: 0x63           <-- the 'c'
         p: 0xBF893E8C     <-- the address of the variable s
        &p: 0xBF893E88     <-- the address of the variable p
      p[0]: 0x8048734      <-- the address of the 'c'
        *p: 0x8048734      <-- the address of the 'c'
      p[1]: 0x8048680      <-- INVALID - the value stored just after the variable s (the program may segfault here)
     *p[1]: 0x55           <-- INVALID - the value stored at location 0x8048680 (again, the program may segfault here)
   (*p)[1]: 0x62           <-- the 'b'
   *(p[1]): 0x55           <-- INVALID - the same as *p[1]
      (*p): 0x8048734      <-- the address of the 'c'
    (*p)++: 0x8048734      <-- the address of the 'c' - the pointer (s) is POST incremented
   (*p)[0]: 0x62           <-- the 'b'
      (*p): 0x8048735      <-- the address of the 'b'
    ++(*p): 0x8048736      <-- the address of the 'a' - the pointer (s) is PRE incremented
   (*p)[0]: 0x61           <-- the 'a'
      (*p): 0x8048736      <-- the address of the 'a'
         s: 0x8048736      <-- the address of the 'a'

Memory Map

This map relates to the execution trace above
These values and addresses will probably be different each time you run the program
Accessing memory that has been marked as not valid in this table is a bad idea. It will very commonly make your program SEGFAULT

Address Value ASCII Variable Valid? Notes
...
0xBF893E93 0x08 ? (MSB) No
0xBF893E92 0x04 ? No
0xBF893E91 0x86 ? No
0xBF893E90 0x80 ? (LSB) No This is p[1] 0xBF893E8C + (sizeof(char*) * 1) → 0xBF893E8C + (4 * 1) → 0xBF893E8C + 4 → 0xBF893E90
0xBF893E8F 0x08 s (MSB) Yes
0xBF893E8E 0x04 s Yes
0xBF893E8D 0x87 s Yes
0xBF893E8C 0x34 s (LSB) Yes This is p[0] 0xBF893E8C + (sizeof(char*) * 0) → 0xBF893E8C + (4 * 0) → 0xBF893E8C + 0 → 0xBF893E8C
0xBF893E8B 0xBF p (MSB) Yes
0xBF893E8A 0x89 p Yes
0xBF893E89 0x3E p Yes
0xBF893E88 0x8C p (LSB) Yes
...
0x08048737 0x00 '\0' Yes This is s[3] 0x08048734 + (sizeof(char) * 3) → 0x08048734 + (1 * 3) → 0x08048734 + 3 → 0x08048737
0x08048736 0x61 'a' Yes This is s[2] 0x08048734 + (sizeof(char) * 2) → 0x08048734 + (1 * 2) → 0x08048734 + 2 → 0x08048736
0x08048735 0x62 'b' Yes This is s[1] 0x08048734 + (sizeof(char) * 1) → 0x08048734 + (1 * 1) → 0x08048734 + 1 → 0x08048735
0x08048734 0x63 'c' Yes This is s[0] 0x08048734 + (sizeof(char) * 0) → 0x08048734 + (1 * 0) → 0x08048734 + 0 → 0x08048734
...
0x08048680 0x55 No This is *p[1] or *(p[1])
...
Personal tools
Namespaces

Variants
Actions
Navigation
Toolbox