Assumes rather than knows. "C-string" is a convention that a
char*
points to an array of characters, where there is null value after the last letter of the text. There can be other legit uses for a
char*
pointer, where there is neither no array or no null at end, but functions that expect C-string should never be called with such pointers.
Function overloading.
Each function must have an unique signature. The calling code has signature of the function embedded and exactly one function implementation in the object files may have that signature. In the last phase of compilation a linker tool connects function calls to the implementations of those functions, producing the executable program.
In C language the name alone was the signature. One did need a different name for each mathematical operation that you could do for more than one numerical type. For example logarithm:
logf
for floats,
log
for doubles and
logl
for long doubles. Inventing names that do not collide, yet mean something, was not fun.
The C++ language does include the types of the parameters to signature of the function. Therefore,
log(float)
,
log(double)
and
log(long double)
are three unique functions even though they all have name "log". The reuse of same name is "overloading".
In
std::cout << foo;
the << is an operator and operator is a function. There are many functions that all have "name" << and the left operand is "ostream" (the type of cout". The functions do differ by the type of the right operand. If the "foo" has type
const char *
(char* can implicitly convert to const char*), then the signature matches the function that expects a C-string and prints readable text.
Some (but not all) of those << functions are listed here:
http://www.cplusplus.com/reference/ostream/ostream/operator%3C%3C/