Does it ever. From today's point of view, C's declaration syntax is just bizarre, especially if you spent some time with a "modern" type system[1]. The result of this declaration-mirrors-usage cleverness is not just the more encompassing insanity like the emergence of the "spiral rule", as found here: [2]. (Isn't it fun that that site promises to enable "any C programmer to parse in their head any C declaration!"? You know you have a problem when that's a novelty.)
It's also the emerging little paper cuts, like the fact that it should be "char* c" with the * hugging the char because * modifies the type and so is part of it, but because of the "mirror usage" concept you better actually write "char *c", because that's how the parser groups it, as part of the variable.
In effect, multiple declarations in one statement must have confused many novices, when they wrote something like "char* p, q", and surprisingly got a "char* p" and a "char q".
> Students have enough trouble mentally separating the concepts of declaration and usage, without the syntax conspiring to blur that crucial difference.
Yeah. I learned C in the 90s (and fortunately by now know exactly where to distribute my "volatile"s and "const"s in a complex type), but I still remember how confusing it was that the * practically did the opposite in declaration vs. usage. In a declaration it makes a pointer, in usage it dereferences it.
Consider the very important difference between those:
char *p = q; *p = q;
Fun.
[1] "Modern" in quotes, because one prime example, Haskell, is old enough to appear in this 1996 article.