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