I’m reading the POSIX specification and I can’t fully understand how file descriptors, file descriptions and streams interact.
FILE* f1 = fopen("a.txt", "r");
int fno = fileno(f1);
FILE* f2 = fdopen(fno, "r");
// is it true?
assert(fileno(f2) == fno);
// does it close only f1 or f2 too?
fclose(f1);
fgetc(f2); // valid?
(Question is in the comments.)
The C standard library gives you the opaque pointer
FILE*, a file handle, which you can manipulate withfopen()/fclose(), and access withfread()/fwrite().POSIX offers a notion of file descriptors which are integers. You can manipulate those with
open()/close(), and access withread()/write().For every open file handle
FILE * fpon a POSIX system, you can get the underlying file descriptor withfileno(fp). Conversely, for an existing file descriptorn, you can open a standard file handle withfdopen(n).In other words, the POSIX file descriptors are an operating system primitive which is used to implement the C standard io library. Note that POSIX file descriptors also serve as handles for sockets.
Your final call to
fgets()is undefined because thefclose()invalidates the file handle, and consequently its underlying file descriptor.fdopen()does not duplicate the file descriptor.