Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 9 years ago.
Improve this question
I was confused by the numerous standards and interfaces for C and C++ programming. There's ANSI C, ISO C, GLIBC, POSIX, Win32, MFC, et cetera. What are the differences between these standards, and how are they related to each other? Under what scenarios would you pick a particular standard? Is there a diagram showing the relationships?
ANSI / ISO C
ANSI C / ISO C are standards designed to support an incredibly broad array of different systems and allow compiling legacy code from ages past. We can call this "standard C". Because C is standardized, there are many implementations.
Half of the C standard refers to the language itself, which includes specific guarantees about what types are available, what syntax you can use, et cetera. These guarantees are sometimes too broad to work with comfortably. For example, in standard C, it is guaranteed that at least the following types exist:
short int, which represents at least -32767..+32767
int, which represents at least -32767..+32767
long int, which represents at least -2147483647..+2147483647
Each type in the list must be wider than the last, but there is a lot of leeway for systems to choose different sizes. For example, on a DSP or an old supercomputer all of the types might be exactly the same size. There is also no guarantee that a byte has 8 bits (maybe it has more than 8 bits).
The other half of the C standard specifies the standard library, such as which functions are provided by each header. For example, the <stdlib.h> header must define the malloc() function.
A program written in standard C can be run almost anywhere, as long as you are careful not to rely on non-portable constructs. However, the C standard does not provide very much functionality... so these portable programs cannot do much more than open files or read input from the user on the console.
There are several versions of standard C. The most common ones are C89/C90, C99, and C11. It is not uncommon to find systems which only support C90 (for example, MSVC).
POSIX
POSIX is a much larger and more comprehensive standard which includes standard C as a part of it. POSIX also specifies parts of the operating system. Because POSIX is standardized, there are many implementations.
On a POSIX system, there are some restrictions on the C implementation. For example, on POSIX:
A byte is always 8 bits
Integers are always two's-complement
The / character is always used as a path separator
Certain errors are signaled by setting errno
POSIX also specifies some additions the the standard library, such as
Network sockets
Creating new processes
Multithreaded programming
Memory-mapped IO
A program written to run on POSIX can be run on Linux, Unix, OS X, or other POSIX-compliant systems. These programs will usually require extra work before they can be run on Windows. The POSIX standard includes interfaces for things like networking, process creation, shells, terminals, and filesystems. It is not too difficult to write a sophisticated POSIX program like a web server or a command-line shell.
There are several versions of POSIX.
GLibc
GLibc is the GNU C library. It implements the standard C library, POSIX extensions to the C library, and some extra functionality. GLibc is not standardized and there is only one implementation.
For example, GLibc provides asprintf(), which is like sprintf() but it allocates the buffer automatically.
Programs that use GLibc extensions are not generally portable, although certain extensions are also available on BSD systems.
Win32
Win32 is an API specific to Windows. The API provides functions not available in standard C, such as functions for creating a graphical user interface. Win32 is not standardized and there are only two implementations (Windows and WINE). Win32 provides a large set of interfaces, such as:
Network sockets
Creating new processes
Multithreaded programming
Memory-mapped IO
These interfaces overlap with POSIX, but the function calls are mostly different. For example, on Windows you can create a mutex with CreateMutexEx(), and on POSIX you create a mutex with pthread_mutex_init(). The exception to this is network sockets, which are mostly the same between Windows and POSIX.
Programs written for Win32 will generally only run on Windows and possibly WINE.
MFC
MFC is a library provided by Microsoft which makes it easier to write Win32 applications. It is effectively obsolete and should not be used for new projects. MFC is not standardized and there is only one implementation.
Related
Suppose you are developing two application (A and B).
How can you send some piece of information to B from A if you are only allowed to work at the c++ language level (that is including the standard libraries and STL) ?
Now Im thinking std::ofstream and std::ifstream could be a possible solution (albeit a crude one) ? - but what pitfalls is there and can they be avoided ? (how?).
You just cannot. Standard C++17 does not know about any kind of inter-process communication and does not know much about processes (except thru std::system whose behavior is not really specified). Some operating systems don't have any processes and some of them don't have files and some of them don't have pipes.
Read more about operating systems. I strongly recommend Operating Systems: Three Easy Pieces (which is freely available).
Of course, you can read and write a file, but the synchronization between the two processes should still happen (perhaps by running one after the other, in some operating system specific way, so running A then B, and how that exactly happens is OS specific)
Read that C++17 standard (e.g. the draft here) to check.
Some C++17 implementations might not even have any notion of process. You could have a fully compliant C++17 on some embedded system without any operating system dealing with processes.
My recommendation is to be pragmatical, and use some framework like Boost, Qt, ZeroMQ, or POCO (or old Berkeley sockets) which deals with processes and inter-process communication facilities; you'll likely to find a framework supporting the several OSes you really care about (AFAIK, all of Boost, POCO, Qt know about Linux, Windows, MacOSX and offer a common API abstracting them; but you could find some academic operating system which is incompatible with them; in practice, any framework targeting both Windows and POSIX should be practically enough).
With some curiosity, you may find an OS with a good C++17 implementation which has a very weird API (look into GNU Hurd for an example).
If your IPC facility is based on byte streams, look into text-based protocols (perhaps JSONRPC, SOAP, HTTP, ...). They are easier to code and most of them come with some C++ compatible library...
And with a few months of work and a lot of know how, you might even port a recent GCC or Clang to most other operating systems: they are careful to abstract the requirements on the OS in a clever way.
Remember, you could find OSes which don't even have any file system: look into CapROS or Contiki for some recent example, and look also inside tunes.org where interesting discussions related to your topic, in the past century, have been archived. But with some pain (my guess is a few months of work for a GCC or Clang expert), you'll be able to port a recent GCC or Clang to target it to obtain a C++17 cross-compiler targetting them.
IMHO, a C++ standard library which enables only to "open" one single "file" (supposedly named THEFILE) is conforming to the letter of the C++17 standard. AFAIK, you don't have any guarantee that std::ifstream or std::ofstream works successfully.
BTW, current processors are practically multi-core, so it makes a lot of sense to try running A and B in parallel and doing some IPC (in an OS specific way, perhaps abstracted by some framework or library).
This question already has answers here:
What is meant when a piece of code is said to be portable? [closed]
(3 answers)
Closed 6 years ago.
Around the Internet I see libraries that claim to be written in portable C++,
as if it was a (maybe unofficial) standard.
Is there a precise definition of what is portable C++, and if so, what is it ?
I'm not asking for common practices for writing portable code, but if there really is something we can call "portable c++".
Portable C++ is quite ambiguous.
However, if you want to achieve portability, only use the Standard Library of C++, and no platform specific code (like read, write syscalls on Linux), no compiler specific intrinsics (like GCC's C / C++ extensions), or inline assembly for a specific CPU.
Keep in mind, that even this might not be "portable". You can compile C++ for a wide variety of platforms (including embedded), and not all of these platforms might ship with a Standard C++ library, or have a compiler supporting the latest and greatest C++ features (C++11, C++14 comes in mind).
True portability can not be achieved, you can, however, achieve portability for the most common platforms, or commit to support these X platforms, and build a platform specific solution for each of them (which is a considerable amount of work, and results in a lot of #ifdef OS1 code).
Portable C++ code means that such code can be compiled for (almost) any platform and by any implementation.
So the goals are, it's unimportant if the program should be running on
different operating systems (windows, linux, OSX)
different architectures (x86, x86-64, titanium , sparc, arm)
different runtime libraries/compilers (gcc, clang, MSVC)
To achieve this, you have to consider many aspects
- Don't use implementation defined APIs and behavior, only use the standard library
- Don't use architecture defined assumptions and behavior, like that char has 8 bits, or negative integers are 2-complement and overflow or that int is 32-bit long and so on
Problem is, you often has to use stuff, for which there is no standard in C++, like networking interfaces. So libraries often try to work around this problem, by using different specific solutions for the most popular systems, selected by the preprocessor.
So as you see portability is always to see in a context, because absolute portability is not practical achievable. For example C++ code that is portable for any C++11 compliant compiler (but most compilers aren't 100%, see MSVC 12/2013), or portable for C++11 compliant compilers AND POSIX systems (so all unix systems can use it). And so on.
Recently I got a question from a colleague whether Dinkumware C++ standard library supports POSIX and I don't know how to answer that. To me it is not clear what is the relation between the two.
Does the C++ standard library provide implementations for POSIX interfaces? Or the two actually two separate things that don't correlate with each other but can be used in tandem during development?
I did some googling but cannot really draw any conclusion. There is this article describing the difference between POSIX and standard C, but what about C++ standard libraries?
Difference Between POSIX and Standard C Library
Any enlightenment would be appreciated!
whether Dinkumware C++ standard library supports POSIX ... To me it is not clear what is the relation between the two.
POSIX is the standard for operating system interface. The C++ standard library is not an operating system, so this question needs to be elaborated.
The C++ standard library does not require POSIX, POSIX does not require C++ standard library. However, the C++ standard requires a few things to be compatible with POSIX:
The behavior of a C++ program is undefined if it adds declarations or definitions to namespace posix or to a namespace within namespace posix unless otherwise specified. The namespace posix is reserved for use by ISO/IEC 9945 and other POSIX standards.
The global namespace posix is now reserved for standardization. Valid C ++ 2003 code that uses a top-level namespace posix may be invalid in this International Standard.
For operating systems that are based on POSIX, implementations are encouraged to define the std::system_category() values as identical to the POSIX errno values, with additional values as de- fined by the operating system’s documentation. Implementations for operating systems that are not based on POSIX are encouraged to define values identical to the operating system’s values. For errors that do not originate from the operating system, the implementation may provide enums for the associated values.
Calls to the POSIX functions setenv and putenv modify the environment.
The header <cerrno> is described in Table 43. Its contents are the same as the POSIX header <errno.h>, except that errno shall be defined as a macro. [ Note: The intent is to remain in close alignment with the POSIX standard. — end note ]
streamsize is used in most places where ISO C would use size_t. Most of the uses of streamsize could use size_t, except for the strstreambuf constructors, which require negative values. It should probably be the signed type corresponding to size_t (which is what Posix.2 calls ssize_t).
Specifies that the grammar recognized by the regular expression engine shall be that used by basic regular expressions in POSIX, Base Definitions and Headers, Section 9, Regular Expressions.
Although POSIX is based on C standard library and defers to it, and C standard library is a part of C++ language specification, the C++ standard library normally does not implement the C standard library.
The C standard library, on the other hand, may implement functionality that POSIX requires. A few quotes from The New C Standard: An Economic and Cultural Commentary:
Some of the functions in the C library have the same name as functions defined by POSIX. POSIX, being an API-based standard (essentially a complete operating system) vendors have shown more interest in implementing the POSIX functionality.
Most hosted environments provide the full set of functionality specified here. The POSIX (ISO/IEC 9945) standard defines some of the functions in the C library. On the whole the specification of this functionality is a pure extension of the C specification.
The C Standard, unlike POSIX, does not prohibit the use of functions, macros, type definitions, and objects from other standards, but such libraries must not change the behavior of any of the C-defined library functionality.
On most implementations a byte occupies 8 bits. The POSIX Standard requires that CHAR_BIT have a value of 8. The Digital DEC 10 and Honeywell/Multics used a 36-bit word with the underlying storage organization based on 9-bit bytes. Some DSP chips have a 16- or 32-bit character type (this often has more to do with addressability issues than character set sizes).
Structure or union types defined in system headers are special in that development projects rarely have any control over their contents. The members of structure and union types defined in these system headers can vary between vendors. An example of the different structure members seen in the same structure type is provided by the dirent structure. The POSIX.1 Standard requires that this structure type include the members d_name and d_namelen. The Open Groups Single Unix Specification goes further and requires that the member d_ino must also be present. Looking at the system header on Linux we find that it also includes the members d_off and d_type;...
I would say that C++ standard library and C standard library operates exactly on same level. That means that you find there utilities that allow to do potentially complex operations, but with little requirement on underlying OS - procisely because they have to be portable across all architectures.
Posix on the other side deals with OS layer. So IMHO, almost all that is written in the referenced article applies to C++ standard library as well. The main difference comes from the fact that it is now a C++ library vs. a C Posix one., that means that in addition to portability, you also gain type control, overrides and all other C++ goodies.
POSIX specifically incorporates the C standard up to 2004 by reference:
The facilities provided in POSIX.1-2008 are drawn from the following base documents: […]
ISO/IEC 9899:1999, Programming Languages - C, including ISO/IEC 9899:1999/Cor.1:2001(E), ISO/IEC 9899:1999/Cor.2:2004(E), and ISO/IEC 9899:1999/Cor.3
It additionally incorporates the Fortran-78 standard, without defining system interfaces, and says, “Additional language bindings and development utility options may be provided in other related standards or in a future version.” On most real systems, there is a single "C library" that contains all the bindings from both standards.
Maxim Egorushkin has some examples of language standards that try to be compatible with POSIX.
POSIX is unusual in that it adds new features and guarantees to standard system headers. Most system libraries are more separate from the standard library than that: if you write a program for Windows, you include both <windows.h> and the standard library headers. C library functions link to the MSVC runtime DLL, while system calls link to KERNEL, GDI, etc. Generally, though, you would need to use the system and standard libraries provided by your compiler together, and link to its runtime.
I have previously written C++ code that #includes Unix and Linux API headers and these programs have produced the expected behavior. That said, I don't know if this can be relied on. It's possible that incompatibilities between C and C++ could cause valid C headers to act in unexpected ways when used by C++ programs.
Can Unix and Linux API headers reliably be used by code that will be compiled as C++?
Is this a goal of the authors of those headers? Or are those headers only intended to be valid C?
Are there any known pitfalls when doing this?
Obviously the Unix and Linux distributions are numerous and I don't expect an answer to address every distribution one by one. My expectation is that the same answer will apply to almost all distributions of Unix and Linux and exceptions will prove the rule. If this assumption is wrong, an explanation of that would also be a valid answer.
By Unix headers I mean these:
http://www.unix.org/version3/apis/headers.html
By Linux headers I mean the headers provided by Linux distributions usually as a package named "linux-headers" that allow programs to interact with the Linux kernel. For example, this Debian package:
https://packages.debian.org/wheezy/kernel/linux-headers-3.2.0-4-amd64
I realize the Unix link is only a specification and that each Linux distribution is different but again I suspect it's reasonable to ask this question for most distributions. If that's not true then correct me.
Edit I only mean to refer to headers used by user space programs.
C standard headers like <stdio.h>, <stdlib.h>, and so forth are specified in Appendix D of the C++ standard, which states:
These are deprecated features, where deprecated is defined as:
Normative for the current edition of the Standard, but not guaranteed
to be part of the Standard in future revisions.
The non-deprecated C++ versions of the C standard headers have names like <cstdio>, <cstdlib>, etc., and they technically put their definitions into the std (not global) namespace. So, to be 100% compliant with the non-deprecated part of the C++ spec, you need to write something like this:
#include <cstdio>
int main() {
std::printf("Hello, world!\n");
}
That said, to my knowledge, no existing implementation actually forces you to do this, and in my opinion it is unlikely any ever will. So in practice, you can safely use C standard headers in C++ without much concern.
Also, if you are on (e.g.) a POSIX system, you can generally use POSIX functionality from C++ equally safely. Certainly nobody is going to deliberately break any of this because users would revolt.
However, accidental breakage is conceivable when mixing paradigms. If both the platform and the language standard provide some feature, you should use one or the other but not both. In particular, I would not mix POSIX threading and synchronization mechanisms with standard C++11 threading and synchronization mechanisms, because it is easy to imagine an optimizer knowing too much about the latter and generating code incompatible with the former.
[Update, to elaborate somewhat]
<unistd.h> is an example of what I mean about platform-dependent functionality. It will generally work fine from C++, and neither the library nor the compiler developers will break it gratuitiously because that would be too annoying. So go ahead and call getpid() or pipe() or whatever.
But be aware that mixing paradigms raises all sorts of questions. To name just a few off the top of my head:
Can you call new from a signal handler?
Can you use dup2 onto descriptor 0 to redirect cin?
What POSIX functions can you call safely during static initialization (i.e. before main executes)?
These questions and others like them are not addressed by any spec. The answers depend on your specific implementation and could change between releases.
Having said all that... Just about every non-trivial C++ program relies on platform-specific functionality exposed by some C interface. So what you are describing will work fine in practice provided you (a) have some idea what is going on "under the hood"; (b) have reasonable expectations; and (c) do not attempt to mix standard and platform-specific paradigms.
1) Yes: "standard headers" are standard. You can safely use them regardless of platform.
2) Yes: you can mix C headers (e.g. <stdio.h>) with C++ headers (e.g. <iostream>) in the same C++ translation unit.
3) NO: you should NOT use linux kernel headers in a user mode program, nor vice versa.
Linux kernel headers are intended for kernel-mode drivers, not for "normal", user space applications.
Here is a bit more information:
https://unix.stackexchange.com/questions/27042/what-does-a-kernel-source-tree-contain-is-this-related-to-linux-kernel-headers
http://kernelnewbies.org/KernelHeaders
I have searched hard but still confused why POSIX is called "Portable Operating System Interface", what I learned is that it is some threading library for Unix environment, because when you need to use it under windows you have to use cygwin or "Windows Services of Unix", etc. That's why I am confused why it is called Portable OSIX. I am a professional C/C++ programmer in Windows domain but new in Unix/Linux. Thanks for your answers in advance.
Before Posix, the Unix family tree was becoming very diverse and incompatible. A program written for one Unix was not compatible with a different Unix without significant porting effort.
Posix was one of the attempts to present a common set of utilities and programming interfaces so that your software would be portable to multiple versions of Unix.
Since Posix is about the interface and not the actual OS, it is possible to have a Posix facade on a non Unix OS (such as the Microsoft Windows Services for Unix presenting a Posix facade on top of Windows).
That one or two stragglers have decided to not make it part of their core doesn't not make it any less portable to almost every other important operating system.
POSIX is simply an interface for operating systems that defines concepts like threads, processes, signals, pipes and I/O. This is not the only interface that's portable across multiple interfaces, but is simply one standard. The name was actually defined by Richard Stallman in the 1980s.
The reason for defining POSIX was that many different versions of UNIX were incompatible, because operating systems hadn't agreed on the implementation of threading or processes.
Here are some more links for further research:
The History of Posix: A Study in the Standards Process
POSIX (Wikipedia)
POSIX defines a set of portable C functions, shell, programs that make the life of a programmer easier because given the definitions in POSIX, it is much more easier to write portable code (not just C, but shell scripts too). Imagine if everyone had their own way of doing things!
Not all the operating systems are POSIX compliant, so if you have to develop for those too, you have to do system-specific things. But POSIX is probably the portable standard across different kinds of systems today. Sure, there is ISO C, which is more portable, but then it's hard to write very useful programs in just ISO C!