C/Pointers
From Attie's Wiki
A helper for people starting out with pointers:
test.c
#include <stdio.h> #include <stdlib.h> #include <ctype.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] ); P( (*p)[1] ); P( *(p[1]) ); P( (*p) ); P( (*p)++ ); P( (*p)[0] ); P( (*p) ); P( ++(*p) ); P( (*p)[0] ); P( (*p) ); 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 p (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 is POST incremented (*p)[0]: 0x62 <-- the 'b' (*p): 0x8048735 <-- the address of the 'b' ++(*p): 0x8048736 <-- the address of the 'a' - the pointer is PRE incremented (*p)[0]: 0x61 <-- the 'a' (*p): 0x8048736 <-- the address of the 'a'
Memory Map
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 | 0x63 | '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 | ||||
... |