The while condition is executed for each iteration of the loop. That means getchar() is executed, which removes the \n from the buffer. Then the return value of getchar() (which has now removed that character from the buffer already) is then compared to '\n' which is false (in this case). The while loop then stops, but the getchar() was still executed
This is why you can run into problems when you use side-effects in a conditional statement (whether it be a while loop, if statement, for, etc..)
For example:
Code:
char * p = "some string I got from the user\n";
/* Now I want to delete that \n char */
while (*p++ != '\n')
;
*p = '\0';
/* This code looks right, but I'm actually just setting the \0 at the end of the string to \0 again because when *p == '\n' I still call the p++ and increment p afterwards which then puts it at the position of the end of the string (pointing to the terminating \0) */