Why are UNIX file descriptors not implemented by their own type, especially in C++? [closed] Why are UNIX file descriptors not implemented by their own type, especially in C++? [closed] unix unix

Why are UNIX file descriptors not implemented by their own type, especially in C++? [closed]


History, if nothing else. Back in the 1970s, it probablydidn't seem like a problem to just use int (and the value was,in fact, an index into a fixed size table). Later, changing itto another type would have broken code.


Your question can be divided in two:

Why is POSIX file descriptor int?

Like most of things in already established tools and libraries, the answer is probably historical reasons. James' answer points this out.

Making the file descriptor opaque is probably a good idea, but not for the reason you mentioned. Making the type opaque is good for having a different type based on some parameters. For example, on some systems you may want a long long as file descriptor. However, as it seems to happen, no one nowhere has needed 2 billion open files at the same time and therefore no one has cared to fix this non-existing problem.

On the other hand, such a thing as typedef int file_descriptor; won't fix any of the problems you mentioned above:

It means that they're easy to confuse for other integers...

If you confuse your variables, I have bad news for you. The compiler won't help you either since file_descriptor and int are the same type, so any operation on one is allowed on the other.

... and there's no way of knowing without context what they are, what they point to, whether they're open, etc.

You can't do that with FILE either. That's why you have functions that query the information you seek and return it, just like with FILE. typedefing the type won't give you any extra information.

Why doesn't POSIX have a C++ wrapper for it?

In short, because except Microsoft, no operating system developer is in love with C++. Windows is barely even POSIX, so there is no hope for Microsoft in trying to improve anything POSIX. Other operating systems which are POSIX-compliant have a C API as the de facto system programming language (partly because as n.m. says, almost all languages can bind to C).

In fact, C++ is popular among application developers, but not as much among system programmers. The POSIX committee doesn't seem to be particularly interested in C++ either. That's why you'd see C and only C solutions and arguments with respect to the POSIX API. Also note that POSIX was created to standardize UNIX's interface in particular, which was written in C and one of its most important descendants, Linux, is also strongly bound to C.


The Unix interface is described in terms of the C language, but it is equally important that systems have an ABI, not only an API.

Fancy data structures specific to a programming language complicate the ABI. At the ABI level, you have only low level data types like "32 bit unsigned integer" and simple aggregates thereof.

That being said, the Unix interface does make use of types like pid_t and whatnot, so why not one of these typedefs for file descriptors?

File descriptors have certain well-known values, and when a new file descriptor is opened, the smallest positive value which is available is always used. File descriptor values effectively acts as array indices into a table of descriptors, and the design is deliberately that way. The programmer's model of file descriptors is that there is array-like structure of them in the kernel. The dup2 function can actually duplicate a file descriptor from one slot to another. Such array indices might as well be int, with a negative value for signaling errors.

C typedefs do not buy additional type checking, but they do bring in a little bit of readability and also abstraction: independence from a particular integer type. A fd_t type could be an int on one system and a long on another. But since int has grown to be almost ubiquitously 32 bits wide several decades ago, there is no real need to abstract it for the sake of being able to make it wider under the same name. It's very unusual for a program to need more than two billion open file descriptors.

By contrast, it would be very inconvenient for implementors if a plain int were used instead of, say, pthread_t.

int descriptors did prove to be difficult to swallow for the designers of the Windows Socket API, who invented a SOCKET typedef, whose values are not the lowest available positive integers; just one of the quirks leading to portability annoyances. However, there is a real semantic difference there in that code which relies on these descriptors being small values in a range will either not work or behave inefficiently.

There are historic instances of Unix having been revised to replace a plain int type with some typedef. For instance, in an accept function, the size of the remote address structure used to be just int. Then it became socklen_t. There is no technical need for socklen_t to exist; it was invented as a band-aid solution to bridge the differences between systems that used the traditional int and ones whose maintainers zealously changed the argument to use size_t. While those two types led to the same ABI, there was no problem, until systems with 64 bit size_t, and 32 bit int.