I can show you with assembly listings, compiled on gcc;
c++
char* str1 = "I love StackOverflow";
char* str2 = "I love StackOverflow";
if(str1 == str2) printf("%s and %s are equal", str1, str2);
else printf("%s and %s are not equal", str1, str2);
asm
LC0: // LC0 - LC1 - LC2 these are labels
.ascii "I love StackOverflow\0"
LC1:
.ascii "%s and %s are equal\0"
LC2:
.ascii "%s and %s are not equal\0"
...
mov DWORD PTR [esp+28], OFFSET FLAT:LC0
mov DWORD PTR [esp+24], OFFSET FLAT:LC0 // moves exact same address into stack
mov eax, DWORD PTR [esp+28] // immediately moves one of them into eax
cmp eax, DWORD PTR [esp+24] // now compares the exact same addresses (LC0)
jne L2 // (jump if not equal)
// followed by code that prints if equal then L2 label(followed by code that prints if not equal)
now using []
LC0:
.ascii "%s and %s are not equal\0"
...
mov DWORD PTR [esp+43], 1869357129
mov DWORD PTR [esp+47], 1394632054
mov DWORD PTR [esp+51], 1801675124
mov DWORD PTR [esp+55], 1919252047
mov DWORD PTR [esp+59], 2003790950
mov BYTE PTR [esp+63], 0
mov DWORD PTR [esp+22], 1869357129
mov DWORD PTR [esp+26], 1394632054
mov DWORD PTR [esp+30], 1801675124
mov DWORD PTR [esp+34], 1919252047
mov DWORD PTR [esp+38], 2003790950
mov BYTE PTR [esp+42], 0
lea eax, [esp+22]
mov DWORD PTR [esp+8], eax
lea eax, [esp+43]
mov DWORD PTR [esp+4], eax
// loads the effective address off the stack of the data for both strings
// notice these two address are different, because both strings sit in different places on the stack
// it doesn't even bother comparing them and has removed the "is equal" string
mov DWORD PTR [esp], OFFSET FLAT:LC0
call _printf