What you are doing is called UB, Undefined Behavior. You should ALWAYS allocate the necessary memory for a strcpy.
In fact, you have not even included string.h, your code will not work as strcpy will be an undefined function.
Even if it somehow due to some bug worked, you would ALWAYS get a segmentation fault. You only have 3 bytes allocated, all of which are taken. Your code is exploitable and is a security vulnerability given malicious input
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
int main(void)
{
char *e = malloc(3);
char *b;
strcpy(e, "Hi"); // 3 bytes
strcpy(b, e);
fputs(b, stdout);
}
Segmentation error. We are writing 3 bytes to a region of 0 bytes. (strcpy(b, e))
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(void)
{
char *e = "Hi";
char *b;
strcpy(b, e);
fputs(b, stdout);
}
Segmentation error. Same thing.
Even running your code with string.h,
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
int main(){
char *s = "Hi";
char *t; // Why the need for char *t malloc(3) here ??
strcpy(t,s);
printf("%s",t); // prints "Hi"
return 0;
}
Guess what? Segmentation error.
I am sorry for being harsh, but this is a very important topic new to C users need to learn, as it can introduce security vulnerabilities and unpleasant coding experiences.
ALWAYS validate inputs, and ALWAYS have the necessary space allocated.
If you are having a seg fault, one of the best tools is Valgrind or Asan.
Valgrind you will have to look up on your own, but Asan is:
gcc -fsanitize=address filename -o filename -g
This will catch all buffer overflows making your life much more pleasant.
You must include -g, which attaches your code to the compiled file so Asan can tell you which line your program is failing on.