Skip to main content TerryFunggg Blog

Opaque Type in C

Checking on open directory in C.

c code snippet start

DIR *dir = opendir(path);

c code snippet end

And then I noticed the DIR type, which is interesting.

c code snippet start

/* This is the data type of directory stream objects.
   The actual structure is opaque to users.  */
typedef struct __dirstream DIR;

c code snippet end

on the dirent.h header file, it say this type is opaque to user.

So we just can imagine the DIR is a directory stream objects normally.

This design is make sence? Private the Dir object..I am not sure..

Ask Grok:

code snippet start

Why it’s good:

- ABI stability is the biggest reason. Linux distributions and long-running programs need the C library to be able to change its internal buffering, locking, or directory-reading strategy without forcing every program to be recompiled. An opaque pointer lets them do that.
- It prevents accidental dependence on layout. If DIR were a public struct, people would start reading its fields, and then glibc could never change them.
- Different C libraries (glibc, musl, dietlibc, etc.) can implement DIR differently while still presenting the same functions. Your code keeps working.

Why it feels awkward:

- You can’t easily inspect the state while debugging.
- Everything requires a function call (readdir, telldir, etc.) instead of just reading a field.
- It looks overly ceremonial compared with Go, Rust, or even modern C++.

code snippet end

Compare to Golang:

golang code snippet start

// inside package os (simplified idea)
type File struct {
    fd   int
    name string
    // other unexported fields
}

func Open(name string) (*File, error) { ... }
func (f *File) Readdir(n int) ([]DirEntry, error) { ... }
func (f *File) Close() error { ... }

golang code snippet end