Most C compilers will allocate name
and address
on the stack, next to each other in memory. I tested it with GCC on a Linux machine, and address
came after name
in memory; other C compilers might as well do it the other way around. It is also possible for compilers to allocate a few bytes of unused space between name
and address
, for memory alignment reasons; though this is uncommon for char arrays.
Let's assume address
comes after name
. Memory is allocated like this (lowest address on top):
name[0]
name[1]
name[2]
...
name[19]
name[20]
address[0]
address[1]
address[2]
...
address[29]
address[30]
base pointer
return address
stack frame of caller
As pointed out by mafso, strings are stored with a trailing NUL character, so the name should be 20 characters max (its last character will be in name[19]
, the NUL terminator in name[20]
), and the address should not exceed 30 characters.
Enter a name of 21 characters, and the NUL terminator will be in address[0]
, only to be overwritten immediately thereafter by the address. Any additional characters entered beyond 21, will be overwritten too. puts(name)
will print the 21 characters stored in name
, followed by whatever the user entered in address
; effectively, name and address are concatenated. puts(address)
will print address in a normal fashion, since it starts printing at address[0]
.
Any attempt to enter an address of more than 30 characters, will overwrite the base pointer and/or return address, which is very likely to make function main
crash upon return. Obviously, the same happens when you enter a name of more than 51 characters.
By carefully crafting the excess characters that will overwrite the return address, it is possible to make the program do something else than crash. Skillful hackers can use this to good fortune; this is what makes buffer overrun vulnerabilities so notoriously dangerous.