When you write
node* first_block = (node*)arr;
you are not changing anything in memory, you get a pointer to the area in memory, the type of the pointer determines how the area is treated in regard to pointer arithmetic.
first_block->next
will be a pointer that is determined by the characters in the array.
as a comparison say you have a char* pointer to the same array
(if arr is declared at global scope it will contain 0's)
char* q = arr;
node* p = (node*)arr;
arr[1000]
+----------------------+
q -> | | | | |
| 0 | 0 | ... | 0 |
p -> | | | | |
+----------------------+
when you do
q = q + 1;
// you move the character pointer one char forward since q is a char pointer
when you do
p = p + 1;
// you move the node pointer sizeof(node) chars forward since p is a node pointer
when you do *q you get the character value of where q points to, *p gives you the node value from the char arr, i.e. the characters are interpreted as a node struct.