A couple of notes in addition to what @Alex correctly points out in his answer. First
char *changeL(char *s); char *changeL(char *s) { .... }
There is no need for a prototype before the function if the function is one line below. A prototype is used to inform code below it that the function described by the prototype exists and is defined elsewhere. If you define the function immediately below the prototype it makes the prototype irrelevant.
Second as noted in Alex's answer, on a overwhelming majority of systems, a String Literal, e.g. the "Something Here" in char *s = "Something Here"; is immutable and resides in read-only memory and any attempt to modify the string literal generally results in a SegFault.
Instead you need to create an array of characters which can be modified, e.g.
char first[] = "HELLO My Name is LoL";
or with C99+ you can use a Compound Literal to initialize first as a pointer to an array of char, e.g.
char *first = (char[]){ "HELLO My Name is LoL" };
In both cases above the characters pointed to by first will be modifiable.
Addition Per Comment
"can you also explain to him why is he getting segfault at upper[i] += 32;"
Yes. At mentioned above, when you initialize a pointer to a String Literal on virtually every current system (ancient systems had no distinction or protection for read-only memory -- all memory was writable). In the current day, creating a string literal (e.g. "foo") creates the string in memory which cannot be modified. (for ELF executables, that is generally in the .rodata section of the executable -- dissecting closer ".ro...data" meaning "read-only data")
When any attempt is made to change data that cannot be modified, a Segmentation Fault generally results because you have attempted to write to an address within a segment that is read-only. (thus the Segmentation Fault -- of SegFault)
In the code above as originally written with
first = "HELLO My Name is LoL";
If you compile to assembly (on Linux, e.g. gcc -S -masm=intel -o mysaved.asm myfile.c you will see that the string "HELLO My Name is LoL" is in fact created in the .rodata section. You do not have any ability to change that data -- you now know what happens when you try :)
The code as written in the Question also shows confusion about what the pointers first and second actually point to. By assigning the return of changeL to second, there is no new memory created for second. It is no different than simply assigning second = first; in main(). second is just a separate pointer that points to the same memory referenced by first. A more concise version of the code would be:
#include <stdio.h> void changeL (char *s) { for (int i = 0; s[i]; i++) if (s[i] >= 'A' && s[i] <= 'Z') s[i] += 32; } int main (void) { char first[] = "HELLO My Name is LoL"; char *second = first; printf("%s\n", first); changeL(first); printf("%s\n", second); return 0; }
(note: both header files in the original code are unnecessary, <stdio.h> is the only required header)
To illustrate second simply points to first:
Example Use/Output
$./bin/chars HELLO My Name is LoL hello my name is lol