ASCII strings do not undergo any special encoding/decoding, so they appear literally in the binary and will appear when the binary is interpreted as a (mostly garbage-y-looking) ASCII file. If you think about it more deeply, the only systematic alternative to storing them in the binary would be some horrible OS-wide central registry of all strings for all programs. If they were stored in a separate file they could get separated from the binary.
However, the OP seems to beg a larger question about code layout and just what compilation does with read-only data such as strings. A more educational way to 'find' the string is to see the intermediate compilation stage of human-readable assembly, where the string will be laid out and referenced by a label. The linker (next compilation stage) will then resolve the label to a numeric offset from the beginning of the binary. Note the .rodata
("read-only data section") label below.
From the gcc manpage:
-S Stop after the stage of compilation proper; do not assemble. The output is in the form of an assembler code file for each non-assembler input file specified.
Results:
.file "foo.c"
.section .rodata.str1.1,"aMS",@progbits,1
.LC0:
.string "password"
.LC1:
.string "Incorrect password"
.section .text.startup,"ax",@progbits
.p2align 4,,15
.globl main
.type main, @function
main:
[assembly language instructions follow]