The stylistic differences are wide. Learning to for instance do C style APIs using opaque types, extended macro-fu, broader use of function pointers, etc. are the sorts of non-obvious things that good C developers do that you'll mostly miss working just on C++ code-bases.
I don't think that non-obvious and "good developers" should be joined together in one sentence. It's possible to do a lot of macro magic, it's possible to do a lot of function manipulation, but this is not good development. This is efficient development when you are working with projects or systems that require that sort of thing (maybe large dataset manipulation or embedded systems), but in my opinion, doing those things is bad programming.
The reason is simple: They are difficult to understand. Code is communication, and there are two listeners - and when you are pushing function pointers around using macros, the human is going to have huge problems understanding what you are trying to achieve.
So I don't think exploiting particular features of a language to extreme levels when it is unneccesary makes you a good programmer in that language - I actually think it makes you worse.
It's like writing a book - you have a certain vocabulary at your disposal, and you can say almost anything you want with that vocabulary. There are different levels of obscurity in the words you use you can reach - you gain in expressiveness, but you narrow your audience. When you write a book for molecular biologists, then the particular terms you use should not be the same as when you write a biology textbook.
That's why I think that one can be a good C programmer without going much deeper than the C subset commonly used in C++.
This is part of my general philosophy in programming - clarity, simplicity and structure first, efficiency second. The machines will catch sooner or later, anyways.
It's not that those features aren't exposed in C++, it's that C++ has different (more modern) mechanisms for doing the same thing.
C++ has templates, so you don't need to do as much with macros. C++ has virtual functions and overloaded operators (allowing for functors), so you don't need to do as much with function pointers. Structures can have methods in C++, so the way that you'd set up an opaque type is quite different in C++.
C++ also has about 10000 other features as well though, which is what makes it unwieldy to learn. The patterns mentioned above aren't about efficiency; they're about encapsulation.
Just to give an example -- in C++ if you want to set up a callback, for example with an observer pattern, you'd use a pure virtual function (and then pass in a concrete instance of that class) or a functor. You can't do that in C, so you use a function pointer. You learn to work with function pointers more because they're a necessary part of designing C APIs, whereas they're not in C++.
(Note that it's the language I'm best at, followed by C, so this isn't random C++ hating.)