The C language seems to really like reading/writing data and then modifying it, or modifying data and then reading/writing it, which can make for some dense one-liners full of side-effects. The pre- and post- increment and decrement operators, and the fact that assignments are expressions, seem to encourage it - especially in combination with the short-circuiting boolean operators.
In old C, they would write code like the function below. This is based on a function from The C Programming Language, and it makes the assumption that bufp points to a buffer that's at least one byte long.
/* Read a line into a lim-sized buffer at bufp, returning strlen(bufp) */
int getline(char *bufp, int lim) {
int c;
char *p = bufp;
while (--lim > 0 && (c = getchar()) != EOF && (*p++ = c) != '\n')
;
*p = '\0';
return p - bufp;
}
But nowadays, in modern C code, I think most people don't write such terse code. I guess it's because the only people who still code in C are those who have no choice, and so they prefer clarity over compactness.