relptr.c (2723B)
1 #define HEADER_IMPL 2 #include "relptr.h" 3 4 #include <string.h> 5 #include <stdio.h> 6 7 /* defining a struct is guaranteed to introduce a new type, and allows us to 8 * have a semblance of strong-ish typing for relptrs. this avoids nasty bugs 9 * where you confuse two different relptr types with the same backing type. 10 */ 11 typedef struct mylist_relptr { 12 int64_t v; 13 } mylist_relptr_t; 14 15 /* our example type, a singly linked list using relative pointers. 16 */ 17 struct mylist { 18 int a; 19 mylist_relptr_t next; 20 }; 21 22 static void 23 mylist_append(struct mylist *restrict list, struct mylist *restrict node); 24 25 static void 26 mylist_print(struct mylist const *list); 27 28 /* i like defining helper functions that give me a more compact way of using 29 * the RELPTR_XXX() macros. this also makes debugging slightly easier as you 30 * can step into the helper functions and inspect the relative pointer value 31 * and the absolute pointer value. 32 */ 33 static inline mylist_relptr_t 34 mylist_abs2rel(void const *restrict base, struct mylist const *restrict absptr) 35 { 36 mylist_relptr_t res = { 37 .v = RELPTR_ABS2REL(__typeof__ (res.v), base, absptr), 38 }; 39 40 return res; 41 } 42 43 static inline struct mylist * 44 mylist_rel2abs(void const *base, struct mylist_relptr relptr) 45 { 46 void *res = RELPTR_REL2ABS(struct mylist *, __typeof__ (relptr.v), base, relptr.v); 47 return res; 48 } 49 50 /* a basic implementation to demonstrate usage of the relative pointer helpers. 51 */ 52 static void 53 mylist_append(struct mylist *restrict list, struct mylist *restrict node) 54 { 55 if (list->next.v != RELPTR_NULL) { /* have next element in list */ 56 mylist_append(mylist_rel2abs(list, list->next), node); 57 } else { /* at end of list */ 58 list->next = mylist_abs2rel(list, node); 59 } 60 } 61 62 static void 63 mylist_print(struct mylist const *list) 64 { 65 printf("mylist:\n"); 66 67 size_t i = 0; 68 while (list) { 69 printf("\t%zu = { %p, { a: %d, next: %p, } }\n", 70 i++, list, list->a, mylist_rel2abs(list, list->next)); 71 list = mylist_rel2abs(list, list->next); 72 } 73 } 74 75 int 76 main(void) 77 { 78 struct mylist buf[4], buf2[4]; 79 struct mylist *foo = buf, *bar = buf + 1, *baz = buf + 2; 80 81 foo->a = 1; 82 bar->a = 2; 83 baz->a = 3; 84 85 /* with custom types for the relptr, this step is a little opaque... 86 */ 87 foo->next.v = bar->next.v = baz->next.v = RELPTR_NULL; 88 89 printf("before appending to list...\n"); 90 mylist_print(foo); 91 92 mylist_append(foo, bar); 93 mylist_append(foo, baz); 94 95 printf("after appending to list...\n"); 96 mylist_print(foo); 97 98 /* with absolute pointers, copying the list to a different memory 99 * location would cause the list to break (it would still point to the 100 * old memory location). 101 */ 102 memcpy(buf2, buf, sizeof buf); 103 104 printf("after copying to different memory location...\n"); 105 mylist_print(buf2); 106 107 return 0; 108 }