char *t = malloc(2);
this means you have created a pointer to a memory location that can hold 2 bytes
+-+-+
t -> | | |
+-+-+
when you do
t = "as";
now you made t point to somewhere else than what it originally was pointing to. now it no longer points to the heap
t = realloc(t,sizeof(char)*6);
now you are taking the pointer pointing to read only memory and try to realloc it.
when you use malloc you allocate space on the heap. t in this case is a pointer to that location, an address of where the block is.
in order to put something in that spot you need to copy the data there by dereferencing t, this is done by writing * in front of t:
*t = 'a'; // now 'a' is where t points
*(t+1)='s'; // now 's' is behind a, t still pointing to 'a'
however in C, a string is always terminated with a 0 (ASCII value) written as '\0' so in order to make it a string you need to append a \0
+-+-+--+
t -> |a|s|\0|
+-+-+--+
in order to do this you need to malloc 3 bytes instead, than you can add the \0 by writing *(t+2)='\0';
now t can be treated as pointing to a string and used in functions that takes strings as arguments e.g. strlen( t ) returns 2