Why did the 16-bit _lopen and _lcreat function return -1 on failure instead of 0?
Some time ago, I discussed why
HANDLE return values are so inconsistent, and I traced it all the way back to the 16-bit
_lcreat functions, which returned
-1 on failure.
But why do those functions return
-1 on failure instead of zero?
_lcreat functions were Windows versions of the C runtime
_creat functions. The C runtime functions came in four different versions depending on which MS-DOS memory model you were using, and the convention was that when Windows adopted a C runtime function, it used the “large” version with the
L prefix, since that is the most general version.
Okay, so why did
-1 on failure?
Because they were MS-DOS-compatible versions of the Unix functions
creat. They even preserve the dropped silent “e” at the end of
Okay, so why do those functions return
-1 on failure?
On Unix, the return value is an integer that represents a file descriptor, valid file descriptors are integers starting with zero. Every process comes with three predefined file descriptors:
|stdin (standard input)
|stdout (standard output)
|stderr (standard error)
Files opened by the program begin with file descriptor 3.
-1 is used to represent failure because 0 was already taken.
And that value of
-1 carried forward, through a chain of backward compatibility, to Win32 as the numeric value of
INVALID_. We saw a little while ago one of the consequences.