I think none of the answers fully answered op's question: op wanted to dereference 'h' to 'i', and he also wanted to know the reason that segmentFault came from his first code snippet
Combined above answers/comments, I list a full answer here:
A. op's first confusion comes from the concept difference between char s[] and char *s:
char *s="hello"; is to place "hello", the string literal, in the read-only memory and make s as a pointer to this string literal, making any writing operation illegal. While if define :
char s[]="hello"; is to put string literal in read-only memory and copy that string to another allocated memory on the stack, so that you can read/write directly on the stack memory (still, you are not touching read-only memory).
So dereference to char *test will given you a constant char, which is the first letter of a string literal located on read-only memory, that's the reason trying to char a = (*tester)++ will fail, because this is a pointer operation on read-only memory, the behavior is undefined.
B. why the second code snippet works ?
writing a = *tester; means you declare another variable char a, then on stack memory, allocate some space for a char and initialize its value to be 'h' ;
This is equivalently to have below:
char a;
a = 'h';
Of course you can increment a.
Here is the example to the explicitly print out the address : run link
#include <stdio.h>
int main()
{
char * tester = "hello";
printf("tester first letter address=%p\n", tester); // print out address should be something like 0x400648
printf("tester second letter address=%p\n", (tester+1)); // print out address should be something like 0x400649
char a;
a = *tester;
printf("a address=%p\n", &a); // print out address should be something like 0x7ffe0bc6aab7
a++;
printf("a address=%p\n", &a); // print out address should be something like 0x7ffe0bc6aab7
return 0;
}