What's happening is something like this.
The literal "NewbieHack.com" is really pointer to a 'string' (or array) of characters that is null terminated by the compiler. This resides in a segment of RAM somewhere at a given address, e.g.
0xface0000 = 4E 65 77 64 69 65 48 61 N e w b i e h a
0xface0008 = 63 6B 2e 63 6f 6D 00 c k . c o m \0
when invoking the function in your example
Send_A_String("NewbieHack.com");
the compiler is passing the address to the function. As such, Send_A_String is looping through the characters in the string, printing them out until it encounters the the null character (or 0).
There is a subtle difference in the syntax here that is important. In the function definition that lists the arguments 'char *StringOfCharacters' means that StringOfCharacters is a pointer (an address) to a character. Later, the syntax (*StringOfCharacters > 0) says deference the address contained in the variable StringOfCharacters and use the value there. The use of the '*' does not have the same meaning in both cases. I'll see if I can illustrate:
void Send_A_String(char *StringOfCharacters) /* StringOfCharacters = 0xface0000 */
{
while(*StringOfCharacters > 0)
/* iteration 1 : *0xface0000 = 0x4E or 'N' so print it out below */
/* iteration 2 : *0xface0001 = 0x65 or 'e' so print it out below */
/* iteration 3 : *0xface0002 = 0x4E or 'w' so print it out below */
...
/* iteration 15 : *0xface000e = 0x00 or 0 or NULL so stop */
{
Send_A_Character(*StringOfCharacters++);
/* here the *StringOfCharacters gets done first */
/* the ++ is applied after the function returns */
/* iteration 1 : print 'N' then increment, StringOfCharacters now = 0xface0001 */
/* iteration 2 : print 'e' then increment, StringOfCharacters now = 0xface0002 */
/* iteration 3 : print 'w' then increment, StringOfCharacters now = 0xface0003 */
...
/* iteration 14 : print 'm' then increment, StringOfCharacters now = 0xface000e */
}
}
Hope that helps.