* It does not work on a field, but on the whole struct. Either all fields are public or all are private. The latter case forces you to write getters/setters for properties you want users to access, and that in C can be even more cumbersome as you need to write the definition in the .h and the implementation in the .c.
* It breaks, without an explicit and specific and error message, several actions. As it's mentioned in the article, malloc isn't possible, but neither are copies by value, sizeof() breaks... And those will break with an "incomplete type" error message, not a "this type is intentionally made private", which can add confusion in some situations.
* Completely incompatible with inlining code. Considering a lot of people still use C precisely for its performance, I think this can be a drawback in a lot of usecases.
I honestly think that hiding struct declarations should be done sparingly, and preferably limiting it to cases where it's actually necessary (for example, a library that doesn't expose internal struct fields so the same executable works with different versions of the dynamic library; or proprietary libraries that want to expose as little as possible). In the end it's still easy to bypass, and the distinction between header and code files already provide an indication of which functions you should use and which ones you shouldn't.