4

I´m migrating a simple socket client program from Linux to Windows (VS2012). The program uses the regular close, read and write functions.

When compiling in VS2012, I´m getting the following warnings:

warning C4996: 'close': The POSIX name for this item is deprecated. Instead, use the ISO C++ conformant name: _close

warning C4996: 'write': The POSIX name for this item is deprecated. Instead, use the ISO C++ conformant name: _write

warning C4996: 'read': The POSIX name for this item is deprecated. Instead, use the ISO C++ conformant name: _read

The solution is simple - just to add the underscode - but...

What´s the real difference between close and _close, read and _read, write and _write ?

Just changing to the underscore version will preserve the same behaviour ?

Mendes
  • 17,489
  • 35
  • 150
  • 263
  • Pretty much as it says... there are the POSIX names, and the names with underscores, and the POSIX names are deprecated since Windows doesn't actually support POSIX. – user253751 Apr 05 '16 at 23:38

3 Answers3

4

When compiling in VS2012, I´m getting the following warnings

Wow, those are hilariously misleading messages. Good job, Microsoft.

They seem to suggest that _close, _read and _write are somehow ISO C++ functions.
They are not!

What's the real difference between close and _close, read and _read, write and _write ?

Microsoft has apparently reimplemented the POSIX functions close, read and write. The difference is that, when reimplementing, they've chosen to rename those functions with a leading underscore, because the ISO C++ standard says that a leading underscore is what the implementation (i.e. Visual Studio) should use for internal/built-in functions.

Just changing to the underscore version will preserve the same behaviour ?

I'm not going to enumerate the various potential differences here. As a matter of course, for full information on how those functions work and how to use them, read their documentation. The direct answer, though, is not to assume that the behaviour is the same as that of the similarly-named POSIX functions.

Lightness Races in Orbit
  • 378,754
  • 76
  • 643
  • 1,055
4

The error message is a political statement, not an actual truth.

Since _close is claimed to be "ISO C++ conformant", the insinuation is that the POSIX close naming is not ISO C++ conformant.

That is complete rubbish.

The names with underscores is simply how Microsoft has implemented an imitation of a subset of POSIX in their library, for decades. (With extensions, such as the _spawn* family of functions, which make up for the lack of fork).

The names are ISO C and C++ conforming in the sense that they are confined to a reserved namespace. If you, the programmer, uses an identifier like _close as an external name, then the behavior is undefined. But that doesn't mean it's a good idea for language implementors to use such identifiers for their public API's. They are useful for internal (perhaps undocumented) identifiers. Microsoft made a regrettable choice to create some API's with ugly names once upon a time, and later crafted a compiler error message to retroactively justify it.

But, look, the Windows API is chock full of identifiers which are not confined to the _[a-zA-Z0-9_]* namespace, such as CreateWindow, and WaitForSingleObject.

If close is not "ISO C++ conformant", then neither are these!

In fact ISO C and C++ allow implementors to have additional library functions with names in the ordinary namespace, such as close or WaitForSingleObject. A name like _close only conforms in the sense that no future ISO C or C++ standard will likely use it. But that's also true, practically speaking, of the identifiers of any major API, like POSIX or Windows.

If you're a minor player in the world of system API's, and you give a function some short name (that is, say, an English dictionary word) even if it doesn't clash with ISO C now, a future standard could run its proverbial bulldozer over it. There is no danger of that happening to the POSIX functions.

Kaz
  • 55,781
  • 9
  • 100
  • 149
2

The POSIX names of the functions are only guaranteed to work on a true POSIX system. VisualC++ implements the POSIX names to aid porting code over, however the ISO standard uses underscore-prefixed names.

POSIX can be considered the "Unix platform API" - so strictly speaking it is entirely distinct and separate from the C and C++ standard libraries (which are ostensibly platform neutral[1]), so for POSIX to have a name like close, write, and read is fully valid - but only on their platform.

The ISO version uses underscore-prefixes because the C++ standard states ( What are the rules about using an underscore in a C++ identifier? ):

Each name that begins with an underscore is reserved to the implementation for use as a name in the global namespace

The idea being that user application code would presumably want to use close, and write for themselves (because they're so non-specific), but if you import a library using the same names you can't use them yourself or you'll get a name collision error.

Unfortunately the rules on underscore prefixes only came into place long after various APIs and libraries were already well-entrenched, such as POSIX and Win32 - so now we're left with an ugly mix of Various() forms_of_writing = _andNaming( IDENTIFIERS ).

[1] Case-in-point: until recently (i.e. the past few years) there was no standard way to enumerate files and directories in C or C++, you always needed to use a platform-specific API - partly because C predates some computers that never even supported hierarchical filesystems, such as the original Macintosh.

Community
  • 1
  • 1
Dai
  • 141,631
  • 28
  • 261
  • 374