Unless struct _IO_FILE is expanded elsewhere, yes, it's opaque and can only be interacted through a pointer, as it would otherwise be an unsized object.
struct _IO_FILE
{
int _flags;
...
so I suppose this means it's indeed expanded somewhere and, thus, not opaque?EDIT: after some more thinking I assume the key is that we wouldn't be able to have a variable of type FILE, but a pointer, whose size is always known.
> a pointer, whose size is always known
Yeah, this is exactly how it works. You work with a pointer that acts like a void* in your code, and the library with the definition is allowed to reach into the fields of that pointer. Normally you'd have a C API like
struct Op;
Op* init_op();
void free_op( Op* );
void do_something_with_op( Op* );
in the header provided by the library that you compile as part of your code, and the definition/implementation in some .a or .so/.dll that you'll link against.*