Header Files in C/C++, Standard? - c++

Are header files standard or different in gcc vs other compilers?

Its not really clear what you are asking, but the "standard" header files are only standard in the sense that they (should) meet the C/C++ standard (as specified by the governing body, e.g. ANSI, etc.)
Different compilers often meet these standards through different implementations, at least when the standard allows them to do so.
In other words, you should only rely on the behavior that is specified in the standard, as specific implementations may vary slightly.

Standard header files are called so, because they are defined as a part of ANSI C/C++ standard, an so, they will be the same for all compilers, that are ANSI-compliant.

I hope I understand your question but here's my go.
Header files (.h) that go along with a .cpp file to create a class are how you do things in C++.
For most cases, a SomeClass.h will prototype the class, and the SomeClass.cpp will contain the code necessary for the class to work.
If for some reason GCC does something very different for compilation, then I have no idea. I assume it's the same idea for any compiler.

The concept of header files, outside of the standard ones required for the standard library, is not specified by the standard. But using #include to specify files to import is. So that is standard, as well as the general order the compiler searches for those files. And the #ifndef BLAH method for avoiding multiple inclusion is also mandated by the standard, insofar as the behavior of the preprocessor is well defined (although as I said, the standard is silent on whether or not you use them at all). #pragma once is not standard, though, so use it at your own risk.

You may find minor variations between different compiler suites. But more significantly, you will find a variety of libraries and header files across different platforms. For instance, GCC is often found on POSIX systems, so it's quite common to find, say, <pthread.h>, whenever __GNUC__ is pre-defined. This leads to assumptive code like the following:
#ifdef __GNUC__
#include <pthread.h>
#else
#include <windows.h>
#endif
If in doubt, favor the C++ Standard Library when using C++ and the C Standard Library when using C. (But continue to expect a few niggling inconsistencies caused mostly by different compiler versions.)
Also, test that your code builds and runs on different systems. If it works using Visual Studio under Windows and GCC under Linux, you can be somewhat assured that porting your code to other systems will be straight-forward.

Related

How to use standard library macros with std module in C++23

I am currently playing with C++ modules, trying to modernize our company's code C++ base to use modules for the core features. In particular there is the upcoming C++23 std module which seems very interesting as a better alternative to precompiled headers.
So I am using Visual Studio 2022 17.5 Preview 2.0, which has a preliminary support for std module. By the way, I faced a compiler internal error, a bug that I reported to Microsoft.
In all our C++ source files, there is now an import std; statement, and this works quite well. Every identifier that is supposed to be in std namespace seem to be exported as expected. I measured a slight decrease of compilation time compared to the previous use of a precompiled header.
I found out that if you import std;, you have a lot of weird compilation errors in you also #include <> any standard C++ header, because Microsoft compiler get confused and complains about redefinition. So I took care of removing all of them.
My problem is that there are a few macros that are defined in standard library (mostly in C compatibility library), which are obviously not exported because C++ modules by design never export macros.
Our code base use a very limited number of those standard macros, but I think it would be hard to avoid them. Here is the short list of them (unsure it is complete):
stdout
errno
va_start, va_arg, va_end
For the va_* macros, I #include <stdarg.h> and it compiles fine on VS 2022, although it breaks the rule I previously mentioned. This is probably because this header has nearly only macros. But for stdout and errno, I don't know what to so.
Does C++23 specify how to access the important standard macros like stdout or errno when importing std module? Is there a good workaround?
According to the C++ working draft:
A declaration in the standard library denotes the same entity regardless of whether it was made reachable through including a header, importing a header unit, or importing a C++ library module.
So this is probably a bug relative to C++23. Though considering that they only claim partial support for the C++23 modular standard library, it's not surprising.
However, for your specific problem, the issue is mostly solved. Many of these macros come from headers that only export the macros. errno comes from <cerrno>, and assert comes from <cassert>. stdout is a problem because it lives in <cstdio> which provides a lot more than just that macro.

Why does g++ 4.9.0 have std::isnan by default?

My understanding is that the function std::isnan is only available from C++11 onwards. Further, g++ uses -std=gnu++98 unless specifically told not to.
So why does this compile?
>> cat test.cpp
#include <cmath>
int main(int argc, char** argv)
{
return std::isnan(0);
}
>> g++ test.cpp
Is there a flag to take the function out of <cmath>?
Compiler developers are lazy about exactly removing every feature that should only be available in the next version of the standard, especially when related libraries (C99) have it at the same time.
The utility (of validing your code actually obeys a specific standard) is not high enough for compiler writers to work extremely hard at making their compiler provide that service.
Instead, what usually happens is new features are implemented under specific standard flags. Sometimes they are accidentally backported. When the standard finalizes, the partial implementation exists for a while until it gets good enough.
Then work starts on the next version of the standard. The next version flag gives you a less stable development environment, as new features are tried out and discarded and changed.
Some effort it put into not backporting stuff, but it isn't a showstopper.
This is a long-standing issue, documented in the FAQ but in a way that you wouldn't necessarily be able to make sense of.
4.3. _XOPEN_SOURCE and _GNU_SOURCE are always defined?
On Solaris, g++ (but not gcc) always defines the preprocessor macro _XOPEN_SOURCE. On GNU/Linux, the same happens with _GNU_SOURCE. (This is not an exhaustive list; other macros and other platforms are also affected.)
These macros are typically used in C library headers, guarding new versions of functions from their older versions. The C++98 standard library includes the C standard library, but it requires the C90 version, which for backwards-compatibility reasons is often not the default for many vendors.
More to the point, the C++ standard requires behavior which is only available on certain platforms after certain symbols are defined. Usually the issue involves I/O-related typedefs. In order to ensure correctness, the compiler simply predefines those symbols.
Note that it's not enough to #define them only when the library is being built (during installation). Since we don't have an 'export' keyword, much of the library exists as headers, which means that the symbols must also be defined as your programs are parsed and compiled.
To see which symbols are defined, look for CPLUSPLUS_CPP_SPEC in the gcc config headers for your target (and try changing them to see what happens when building complicated code). You can also run g++ -E -dM - < /dev/null" [sic] to display a list of predefined macros for any particular installation.
This has been discussed on the mailing lists quite a bit.
This method is something of a wart. We'd like to find a cleaner solution, but nobody yet has contributed the time.
To explain:
glibc is what provides the standard C library. It supports several modes.
It supports various strict C modes and strict POSIX modes. In these modes, when only standard headers are included, only standard functions are available. In C90 mode, this does not include isnan.
It supports various extension modes. In these modes, non-standard functions are also available. In C90 + extensions mode, this includes isnan. The _GNU_SOURCE preprocessor macro is the one that enables all extensions.
libstdc++ is what provides the standard C++ library. It requires more from glibc than what strict C90 mode offers. Therefore, there are only two options: either libstdc++ does not offer those standard C++ features it cannot provide, or libstdc++ forcibly enables glibc's extensions even in strict ANSI mode. Both mean a failure to conform to the C++ standard, but the former restricts features, while the latter provides them. The latter is seen as the lesser evil.
The only reasonable way to fix this is for glibc to provide some non-standard way to access its extensions even in strict ANSI mode. No such way exists yet, and until such a way is created, non-standard names will be available even in meant-to-be-standard C++ compilation modes.

Apply language standard to just part of a source file?

Is it possible to enforce a C or C++ language standard for just part of a source file? I want to ensure that my source file is C90 compliant, but it depends on some headers that require C99. The compliance of those headers isn't important to me right now (I can compile with C99 for the time being), but I want to minimize effort required to port my code to a more restrictive platform in the future.
In short, I want a language standard to apply to the entire file except for the included headers. Given how header inclusion works in C and C++, I figure that the general problem is to apply a language standard to an arbitrary portion of a given source file.
I'm working with GCC in particular, but I'm also curious if this is possible with other compilers (msvc, clang).
If you want to make sure your code is C90 compatible while still relying on headers that use C99, you can enable the GCC warning flag -Wc90-c99-compat. This allows you to use C99 features, but emits a warning wherever you use features not available in C90. To avoid generating these warnings in your header files (which are presumably correct), enable the warning using a pragma, after you include the files.
This will basically achieve what you want. The warnings will only be emitted for the code you specify.
#include "myheader.h"
#pragma GCC diagnostic warning "-Wc90-c99-compat"
void func(void) { ... }
A stricter version would be to use:
#pragma GCC diagnostic error "-Wc90-c99-compat"
As far as I know, Clang is mostly compatible, but MSVC doesn't really support C99 that well to begin with so you're on your own.
No. You cannot build a file (compilation unit) as partly one language standard and partly another.
What you can do however is split the file into two files and compile each of them using different language standards (just be sure that it is then still well defined to link both object files afterwards).
A better solution would be to ensure that all the code complies with the newer or older language standard and then just use that.

How to portably detect whether a compiler supports <iostream> vs <iostream.h>

I'm working on a utility that needs to be able to compile on both standard C++ compilers and pre-standard compilers. The code can and will be thrown at just about any C++ compiler in existence.
I am looking for a means to robustly and portably determine whether the target compiler supports header files with or without an .h extension. I will also need to detect whether namespaces are supported. Both of these needs may or may not be possible.
A little background: The utility is the Inline::CPP language extension for Perl. The extension automatically includes <iostream>, and tries to make a good guess whether a '.h' is required or not (and of course whether or not the compiler supports namespaces). But it's far from perfect in that regard, and this issue is diminishing the breadth of the utility's usefulness.
So to reiterate the question: How do I portably detect whether a compiler supports standard headers such as <iostream>, or pre-standard headers such as <iostream.h>?
Not in the code, but in the build/configure system. For example in CMake, you could use try_compile and provide it a sample file.
...
try_compile(PRE_STANDARD_HEADERS tmp_builds pre_standard_headers_test.cpp)
if ( ${PRE_STANDARD_HEADERS} )
add_definitions( -D PRE_STANDARD_HEADERS )
endif()
You'd need to make that pre_standard_headers_test.cpp .. just a simple compilable exe that #include <iostream.h> for example.
Then in your normal code just an
#ifdef PRE_STANDARD_HEADERS
would do the trick.
The standard approach for Linux and other Unix-friendly platforms is to use a configure script. The script will generate as its output a Makefile and a config.h header file that turns on or off any compiler features that your code could rely on when available.
For Windows it is kind of expected that you will provide solution and project files for Visual Studio, with a pre-generated config.h header file.

How to view source code of header file in C++?

similar to iostream.h ,conio.h , ...
The standard library is generally all templates. You can just open up the desired header and see how it's implemented†. Note it's not <iostream.h>, it's <iostream>; the C++ standard library does not have .h extensions. C libraries like <string.h> can be included as <cstring> (though that generally just includes string.h)
That said, the run-time library (stuff like the C library, not-template-stuff) is compiled. You can search around your compiler install directory to find the source-code to the run-time library.
Why? If just to look, there you go. But it's a terrible way to try to learn, as the code may have non-standard extensions specific to the compiler, and most implementations are just generally ugly to read.
If you have a specific question about the inner-workings of a function, feel free to start a new question and ask how it works.
† I should mention that you may, on the off chance, have a compiler that supports export. This would mean it's entirely possible they have templated code also compiled; this is highly unlikely though. Just should be mentioned for completeness.
From a comment you added, it looks like you're looking for the source to the implementations of functions that aren't templates (or aren't in the header file for whatever reason). The more traditional runtime library support is typically separately compiled and in a library file that gets linked in to your program.
The majority of compilers provide the source code for the library (though it's not guaranteed to be available), but the source files might be installed anywhere on your system.
For the Microsoft compilers I have installed, I can find the source for the runtime in a directory under the Visual Studio installed location named something like:
vc\crt\src // VS2008
vc7\crt\src // VS2003
vc98\crt\src // VC6
If you're using some other compiler, poke around the installation directory (and make sure that you had asked that runtime sources to be installed when you installed your compiler tools).
As mentioned, it is implementation specific but there is an easy way to view contents of header files.
Compile your code with just preprocessing enabled for gcc and g++ it is -E option.
This replaces the contents of header files by their actual content and you can see them.
On linux, you can find some of them in /usr/include
These files merely contain declarations and macro definitions.The actual implementation source files can be obtained from the library provider e.g the source code of standard C++ Library(libstdc++) is obtainable here.
According to the C++ language specification, implementors do not have to put standard headers into physical files. Implementors are allowed to have the headers hard coded in the translator's executable.
Thus, you may not be able to view the contents of standard header files.