Pointer Arithmetic - MarekBykowski/readme GitHub Wiki

Decay (array "decaying" to a pointer) is a conversion rule: an array name used in an expression converts to a pointer to its first element.

char *t[5];
// t is an ARRAY of 5 elements, each element of type char*

// where decay applies
char **p = t;    // p gets the address of t[0]
func(t);         // the function receives char**
t + 1            // &t[0] + 1 โ†’ step of 8 bytes (sizeof(char*))
t[2]             // *(&t[0] + 2) โ€” decay first, then arithmetic and deref
int a[] = {1,2,3,4,5};
int *p = &a[1];   // points to a[1]
int *q = &a[4];   // points to a[4]

q - p;   // โ†’ 3  (elements, not bytes!)  type: ptrdiff_t
p + 2;   // โ†’ &a[3], advances 2ร—sizeof(int) bytes in memory

// Pointer TO an array (not to an element)
// Note 5 to match a[] above
int (*ap)[5] = &a;   // type: int(*)[5]
(*ap)[1];            // dereference ap, then index [1] -> 2
*ap[1];              // advance to the *next* array (none), dereference what array, UB here
ap++;                // advances sizeof(int[3]) = 12 bytes!

*ap[0]   // โ†’ *(ap[0]) โ€” [] beats * โ€” DIFFERENT THING!
int a[5] = {1,2,3,4,5};
a[2];   // โ‰ก *((int*)&a[0] + 2)

// Indexing an array name is always 3 steps:
// 1. DECAY:   a โ†’ (init *)&a[0]            (array name converts to pointer to 1st element; type int*)
// 2. ADVANCE: ((init *)&a[0]) + 2          (scaled: +2*sizeof(int) = +8 bytes; still address math)
// 3. DEREF:   *(((init *)&a[0]) + 2)       (the only memory read)
// excercise 
int a[] = {0,1,2};
int b[] = {3,4,5};

int (*pa)[3] = &a;

int (*pa[2])[3] = {&a, &b};     // pa is array of 2x elems, each elem of type int(*)[3]
pa[1]      // &b                    (int(*)[3])
*pa[1]     // b is an array lvalue  (int[3])
**pa[1]    // b[0] == 3             (int)

// Get value of b[0]
int (*c)[3] = pa[1];
int d = (*c)[0];   // or *pa[1] -> array name decays to pointer to 1st elemn
                   //    **pa[1] -> deref of pointer to 1st elemn returns 3

// get the pointer to b[0]
int *e = *pa[1];    
// or 
//    int (*a)[3] = &(*pa[1]);   // address of the b array
//    int c = (*a)[0];           // deref and index 0th = 3
//    int *pointer = &(*a)[0];   // get pointer to b[0]
char *cmd0[] = { "ls", "-l", NULL };
char *cmd1[] = { "grep", "foo", NULL };

char **cmds[MAX_CMDS] = { cmd0, cmd1 };   // cmd0/cmd1 decay: char*[] โ†’ char**

/* Another example */
char *s = "literal";
printf("%s\n", s);        // literal โ€” s is char*, 0 derefs

char *t[5] = {"this", "is", "a", "white", "cat"};
char **p = t;             // decay: char*[5] โ†’ char**
printf("%s\n", *p);       // this  โ€” t[0]
printf("%s\n", p[0]);       // this
printf("%s\n", t[0]);       // this
printf("%s\n", *(p+1));   // is    โ€” t[1]; โ‰ก p[1] โ‰ก t[1]
Type 32-bit 64-bit (Linux)
int 4 bytes 4 bytes
long 4 bytes 8 bytes
pointer 4 bytes 8 bytes
ptrdiff_t 4 bytes 8 bytes
uint32_t 4 bytes 4 bytes โ€” always, use this in embedded!