When working with strdup on Windows I found out that _strdup is Windows specific, but when I ran the same code on Linux it required strdup without the underscore. Does anyone know the history behind this difference, as-well as some information on how you have dealt with this problem when writing cross-platform code?
There are several functions that are part of the POSIX specification, i.e. Linux and most other UNIX variants, that are not part of standard C. These include strdup, write, read, and others.
The reasoning for the leading underscore is as follows, taken from the MSDN docs:
The Universal C Run-Time Library (UCRT) supports most of the C
standard library required for C++ conformance. It implements the C99
(ISO/IEC 9899:1999) library, with certain exceptions: The type-generic
macros defined in , and strict type compatibility in
. The UCRT also implements a large subset of the POSIX.1
(ISO/IEC 9945-1:1996, the POSIX System Application Program Interface)
C library. However, it's not fully conformant to any specific POSIX
standard. The UCRT also implements several Microsoft-specific
functions and macros that aren't part of a standard.
Functions specific to the Microsoft implementation of Visual C++ are
found in the vcruntime library. Many of these functions are for
internal use and can't be called by user code. Some are documented for
use in debugging and implementation compatibility.
The C++ standard reserves names that begin with an underscore in the
global namespace to the implementation. Both the POSIX functions and
Microsoft-specific runtime library functions are in the global
namespace, but aren't part of the standard C runtime library. That's
why the preferred Microsoft implementations of these functions have a
leading underscore. For portability, the UCRT also supports the
default names, but the Microsoft C++ compiler issues a deprecation
warning when code that uses them is compiled. Only the default names
are deprecated, not the functions themselves. To suppress the warning,
define _CRT_NONSTDC_NO_WARNINGS before including any headers in code
that uses the original POSIX names.
I've handled that by having a #define that check if the program is being compiled for Windows, and if so create another #define to map the POSIX name to the Windows specific name. There are a few choices you can check, although probably the most reliable is _MSC_VER which is defined if MSVC is the compiler.
#ifdef _MSC_VER
#define strdup(p) _strdup(p)
#endif
Related
This question is about the same subject as strdup or _strdup? but it is not the same. That question asks how to work around MS's renamings, this question asks why they did it in the first place.
For some reason Microsoft has deprecated a whole slew of POSIX C functions and replaced them with _-prefixed variants. One example among many is isatty:
https://learn.microsoft.com/en-us/cpp/c-runtime-library/reference/posix-isatty
This POSIX function is deprecated. Use the ISO C++ conformant _isatty instead.
What exactly is ISO C++ conformant about _isatty? It appears to me that the MSDN help is totally wrong.
The other questions answer explained how to deal with this problem. You add the _CRT_NONSTDC_NO_DEPRECATE define. Fine. But I want to know what Microsoft's thinking is. What was their point in renaming and deprecating functions? Was it just to make C programmers lives even harder?
The fact that _isatty() is ISO C++ conformant makes sense if you think of it like a language-lawyer.
Under ISO C++, the compiler is only supposed to provide the functions in the standard (at least for the standard headers) -- they're not allowed to freely add extra functions, because it could conflict with functions declared in the code being compiled. Since isatty() is not listed in the standard, providing an isatty() function in a standard header would not be ISO C++ compliant.
However, the standard does allow the compiler to provide any function it wants as long as the function starts with a single underscore. So -- language lawyer time -- _isatty() is compliant with ISO C++.
I believe that's the logic that leads to the error message being phrased the way it is.
(Now, in this specific case, isatty() was provided in io.h, which is not actually a C++ standard header, so technically Microsoft could provide it and still claim to be standards-conformant. But, they had other non-compliant functions like strcmpi() in string.h, which is a standard header. So, for consistency, they deprecated all of the POSIX functions the same way and they all report the same error message.)
Names starting with an underscore, like _isatty are reserved for the implementation. They do not have a meaning defined by ISO C++, nor by ISO C, and you can't use them for your own purposes. So Microsoft is entirely right in using this prefix, and POSIX is actually wrong.
C++ has namespaces, so a hypthetical "Posix C++" could define namespace posix, but POSIX has essentially become fossilized - no new innovation in that area.
isatty & co., although POSIX, are not standard C, and are provided as "extensions" by the VC++ runtime1.
As such, they are prefixed with an underscore supposedly to avoid name clashes - as names starting with an underscore followed by a lowercase letter are reserved for implementation-defined stuff at global scope. So if, for example, you wanted to use an actual POSIX compatibility layer providing its own versions of these functions, they wouldn't have to fight with the VC++-provided "fake" ones for the non-underscored names.
Extensions which have no presumption to be actually POSIX-compliant, by the way.
Is there any way to access thread.h file .
I am not able to find thread.h header in windows since threading is related to OS.
I tried using pthread.h an external library , but was never able to find thread.h which according to my professor works in solaris.
This is an excellent example where tagging a question with "C" and "C++" is highly confusing because the answers are entirely different.
If you are coding in C++11 or later, then you should
#include <thread>
and use the std::thread class. You'll be fine.
If you are coding in C11 or later, then you should
#include <threads.h>
However, you may have to wait until your implementation supports it. § 7.26.1 ¶ 2 of the C11 standard says:
Implementations that define the macro __STDC_NO_THREADS__ need not provide this header nor support any of its facilities.
You can check with an #ifdef whether your implementation defines it. At least my GCC does.
For the time being, if you cannot switch to C++, use a third-party threading library like pthreads.
thread.h isn't well defined in the context of c++ standards. If you have a c++11 compliant toolchain, you need to
#include <thread>
as stated in the reference documentation.
Pre standard toolchains probably need to have the standard specified explicitly using the -std=c++0x or -std=c++11 compiler flags.
As you changed your focus to c, including c++ headers won't work. You may try pthread.h.
I will give an example from The GNU C Library documentation:
13.1 Opening and Closing Files
This section describes the primitives for opening and closing files
using file descriptors. The open and creat functions are declared in
the header file fcntl.h, while close is declared in unistd.h.
My question is:
Can unistd.h and fcntl.h be considered as Standard C? As far as I know, they should be part of the Posix standard?
Can we say C Standard Library = Posix functions + C API? I am confused because Wikipedia page for C Standard Library does not include unistd.h but the GNU C Library documentation includes it?
No, unistd.h, fcntl.h, etc, are not standard C.
In general, standard C doesn't include functions that deal with low level file manipulation. For example, fopen, fread, and fwrite are part of standard C library. While POSIX open, read, write functions are not standard C.
As far as I can see, in C11 standard, there is no unistd.h and fcntl.h. So, strictly speaking, they are not part of the C standard.
When it comes to the implementation part, the GNU C library (glibc) is one of them. From the wiki page
glibc provides the functionality required by the Single UNIX Specification, POSIX (1c, 1d, and 1j) and some of the functionality required by ISO C11, ISO C99, Berkeley Unix (BSD) interfaces, the System V Interface Definition (SVID) and the X/Open Portability Guide (XPG), Issue 4.2, with all extensions common to XSI (X/Open System Interface) compliant systems along with all X/Open UNIX extensions.
In addition, glibc also provides extensions that have been deemed useful or necessary while developing GNU.
So, as a part of the POSIX standard, they are available in glibc.
Reference: Check the C11 standard draft version here.
I am currently learning C. I understand that many common functions, like printf and scanf are not actually part of the C language -- they are part of the "standard library" of functions.
My question is, why aren't such functions built into the language? Is it a philosophical/design consideration? A matter of efficiency when compiling programs? A necessity in order to act as a "middle layer" to ensure compatibility with different operating systems? Something else entirely?
They are part of C. A C implementation consists of a compiler and a library (and other components, like a linker).
The C core language includes facilities that make it possible to write library code that can be used by other programs. The standard library portion of the standard specifies a library that can be implemented using the facilities defined in the core language.
Some languages do have things like a print command built into the language. C's facilities for writing and invoking library code written in C are powerful enough that that's not necessary.
Furthermore, most of the library is optional for "freestanding" implementations (mostly for embedded systems). There are implementations that support the full core language but that don't provide most of the C standard library.
And a compiler and library can be provided separately. For example, gcc is a compiler; it's commonly used with different library implementations on different systems (GNU libc on Linux, "newlib" on Cygwin, the Microsoft library on Windows with MinGW, and so forth). Mixing and matching like that would be much more difficult if the library were integrated into the core language.
The C language standard (the link is to the newest freely available draft) defines C. Section 6 defines the core language; section 7 defines the standard library.
The thing is that standard allows two kinds of conforming implementation: hosted and freestading, see N1570 4/p6:
The two forms of conforming implementation are hosted and
freestanding. A conforming hosted implementation shall accept any
strictly conforming program. A conforming freestanding implementation
shall accept any strictly conforming program that does not use complex
types and in which the use of the features specified in the library
clause (clause 7) is confined to the contents of the standard headers
<float.h>, <iso646.h>, <limits.h>, <stdalign.h>, <stdarg.h>, <stdbool.h>,
<stddef.h>, <stdint.h>, and <stdnoreturn.h>. A conforming implementation may have
extensions (including additional library functions), provided they do
not alter the behavior of any strictly conforming program.
By such design, where the libraries are organized as standard headers it's convienent to simply "cut-off" some header if it is not supported.
Note that C standard defines all headers along with function for standard C library. It's included in C standard indeed, not separate thing somewhere else.
They're part of the language, they're just not part of the grammar.
Factoring I/O out into a separate function library buys you the following:
The grammar becomes easier to parse;
You can target a wider range of platforms; any I/O foibles are handled by the library functions, not by hacking the code generator;
You can implement only as much as is needed to support the platform (i.e., an embedded controller probably doesn't need to read or write formatted output);
I noticed that the difference between linux and windows.
strcmpi is in windows C standard libary implementation but it is not in GNU's C standard libary implementation.
Is the function strcmpi in the C standard libary defined by ISO?
How can I get the standard file?
Thank you.
The POSIX Standard (aka, UNIX) has strcasecmp() but it's not part of C99 / ISO-C.
Note: If you compare the above reference with e.g. the one for strcmp() you'll note that the latter explicitly references ISO-C, while the former does not. An useful feature of the OpenGroup references.
Edit: Since the locale-dependency was mentioned as a complication, see the above reference for strcasecmp_l() which allows explicitly specifying the locale to be used for the conversion. Windows has _strcmpi_l() for the purpose, again keeping with its own naming conventions.
Nope, it's a non-standard extension. Unix-like systems commonly have a strcasecmp which performs the same task as MS's strcmpi.
Nope, a quick CTRL+F in the standard returns nothing for strcmpi. This means that it is a non-standard extension (of which both Windows and GNU have a lot).