I am really confused about the following:
char *list = malloc(sizeof(char));
list[0] = 'a';
list[1] = 'b';
printf("%s\n", list);
My expectation was some kind of undefined behavior, because list has only memory for 1 char "object".
But the actual output is ab. Why can I access list[1] when list only has allocated memory for one char?
                        
As per your memory allocation of
sizeof(char)bytes (and considering the allocation is success),is out-of-bound access, which invokes undefined behavior. There can be no expectation from a program causing UB. It can do anything, absolutely anything.
That said,
sizeof(char)is defined (guranteed) to be1in C standard.malloc()before using the return value. Otherwise, the first access,list[0]itself will invoke UB as you'll end up dereferencing an invalid pointer (i.e., accessing invalid memory)chararray as argument to%salso invokes UB.