String literals have static storage duration. That is they are alive during the program execution.
You may consider the first function
char* test(){
return "HELLO";
}
the following way
char* test(){
static char arr[] = { 'H', 'E', 'L', 'L', 'O', '\0' };
return arr;
}
As for the second program
char* test(){
char arr[] = "HELLO";
return arr;
}
then there is returned a pointer to the local array arr
with automatic storage duration that will not be alive after exiting the function. So the returned pointer will be invalid and dereferencing it results in undefined behavior.
From the C Standard (6.2.4 Storage durations of objects)
3 An object whose identifier is declared without the storage-class
specifier _Thread_local, and either with external or internal linkage
or with the storage-class specifier static, has static storage
duration. Its lifetime is the entire execution of the program and
its stored value is initialized only once, prior to program startup.
and (6.4.5 String literals)
6 In translation phase 7, a byte or code of value zero is appended to
each multibyte character sequence that results from a string literal
or literals.78) The multibyte character sequence is then used to
initialize an array of static storage duration and length just
sufficient to contain the sequence.