Looks I am late to the party , but my 2 cents below.
CONCEPT : "We can manipulate data(ie do write operation on memory address) if and only if we own(memory address) accessible by us."
Now as Peter suggested , the core anamoly in the code is related the string literals.
They are special variables (compiler will decay them to special memory address) which are write-restricted & no change is allowed by "users".
Since compiler decayed string literal to special memory address(ie it allocated enough bytes somewhere in memory for all characters of the string & initialised them to correct values & added the terminating '\0' character and finally returns the base address of the memory chunk... [writing this statement makes me more indebted to compiler for making life easier !! ] )
If you made it this far ,I owe you an explanation of special address.To understand this best you need to dive deeper into the memory layout of C program. To digress, this memory loaction is not stack memory (like variable s1) ,nor heap memory(no new /malloc done ) ,global ,static.
Why is it write restricted ( ie not read only) , because in debug mode we can actually change contents of the literal, see below dummy program:
#include <stdio.h>
int main()
{
char s1[] = "My name is Bob.";
//PrintSentenceReversed(s1);
printf ("Stack s1 %s\n" , s1 );
char * s2 = "My name is Bob.";
//PrintSentenceReversed(s2);
printf ("Literal s2 %s\n" ,s2 );
return 0;
}
/* ---- DEBUGGER output , see how s2 contents can be changed without seg fault in debug , but try s2[1]='e' in code & see the code die ... :/
Reading symbols from a.out...done.
/usr/share/gdb/gdbinit: No such file or directory.
(gdb) b 11
Breakpoint 1 at 0x4005f7: file main.c, line 11.
(gdb) r
Starting program: /home/a.out
Stack s1 My name is Bob.
Breakpoint 1, main () at main.c:11
11 printf ("Literal s2 %s\n" ,s2 );
(gdb) p s2
$1 = 0x4006c1 "My name is Bob."
(gdb) set *(s2 +1)='e'
(gdb) p s2
$2 = 0x4006c1 "Me name is Bob."
(gdb) set *(s2+11)='T'
(gdb) p s2
$3 = 0x4006c1 "Me name is Tob."
(gdb) set *(s2+13)='m'
(gdb) p s2
$4 = 0x4006c1 "Me name is Tom."
(gdb) n
Literal s2 Me name is Tom.
13 return 0;
*/
TL;DR: The string literal (below) is write restricted memory & changing it will causes Seg Fault.
char * s2 = "My name is Bob.";
To Fix : dont write to memory which doesnt belong to us .
Hope this made sense. Cheers!!