Cstdio Stdio.H Namespace

cstdio stdio.h namespace

Including cstdio imports the symbol names in std namespace and possibly in Global namespace.

Including stdio.h imports the symbol names in Global namespace and possibly in std namespace.

The same applies for all c-styled headers.


Reference:

C++11 standard

Annex D (normative) Compatibility features [depr] states:

D.6 C standard library headers

1 For compatibility with the C standard library and the C Unicode TR, the C++ standard library provides the 25 C headers, as shown in Table 151.

Which include:

<assert.h> <float.h> <math.h> <stddef.h> <tgmath.h>
<complex.h> <inttypes.h> <setjmp.h> <stdio.h> <time.h>
<ctype.h> <iso646.h> <signal.h> <stdint.h> <uchar.h>
<errno.h> <limits.h> <stdarg.h> <stdlib.h> <wchar.h>
<fenv.h> <locale.h> <stdbool.h> <string.h> <wctype.h>

Further on,

2 Every C header, each of which has a name of the form name.h, behaves as if each name placed in the standard library namespace by the corresponding cname header is placed within the global namespace scope. It is unspecified whether these names are first declared or defined within namespace scope (3.3.6) of the namespace std and are then injected into the global namespace scope by explicit using-declarations (7.3.3).

3 [ Example: The header <cstdlib> assuredly provides its declarations and definitions within the namespace std. It may also provide these names within the global namespace. The header <stdlib.h> assuredly provides the same declarations and definitions within the global namespace, much as in the C Standard. It may also provide these names within the namespace std. —end example ]

Correct order for including both cstdio and stdio.h ?

OK, after some more reasearch I finally came to a conclusion that including the C++ header first, C header later is the correct thing to do.
For example, consider the following C++0x header (from gcc):

/usr/include/c++/4.3/tr1_impl/cstdint:


// ...
#define __STDC_LIMIT_MACROS
#define __STDC_CONSTANT_MACROS
#include_next <stdint.h>
// ...

What it does is that it defines two C99 macros, and only then includes the C99 stdint.h header. The reason is that in C99, some of the features of stdint.h are optional, and only available if those macros are defined. However, in C++0x, all stdint.h features are mandatory.
Now, if I included the C99 stdint.h first, cstdint later, I wouldn't get the mandatory C++0x features because of the header guards in stdint.h.
One could argue that this is the compiler vendor's fault, but that would be incorrect. stdint.h is a system-bundled header (from glibc in this case), which is a C99 header and doesn't know anything about C++0x (it can be an old system, after all) or gcc. The compiler can't really fix all the system headers (in this case to always enable those features in C++ mode), yet it has to provide C++0x support on these systems, so the vendor uses this workaround instead.

stdio.h not standard in C++?

stdio.h is standard, but deprecated. Always prefer cstdio in C++.

[n3290: C.3.1/1]: For compatibility with the Standard C library, the
C++ standard library provides the 18 C headers (D.5), but their use is
deprecated in C++.

[n3290: D.5/3]: [ Example: The header <cstdlib> assuredly
provides its declarations and definitions within the namespace std. It
may also provide these names within the global namespace. The header
<stdlib.h> assuredly provides the same declarations and definitions
within the global namespace, much as in the C Standard. It may also
provide these names within the namespace std.
—end example ]

When using C headers in C++, should we use functions from std:: or the global namespace?

From the C++11 Standard (emphasis mine):

D.5 C standard library headers [depr.c.headers]

  1. For compatibility with the C standard library ...
  2. Every C header, each of which has a name of the form name.h, behaves as if each name placed in the standard
    library namespace by the corresponding cname header is placed within the global namespace scope. It is unspecified whether these names are first declared or defined within namespace scope (3.3.6) of the namespace std and are then injected into the global namespace scope by explicit using-declarations (7.3.3).
  3. Example: The header <cstdlib> assuredly provides its declarations and definitions within the namespace
    std
    . It may also provide these names within the global namespace. The header <stdlib.h> assuredly provides the same declarations and definitions within the global namespace, much as in the C Standard. It
    may also provide these names within the namespace std.

Using the «name.h» headers is deprecated, they have been identified as candidates for removal from future revisions.

So, I would suggest to include the «cname» headers and to use the declarations and definitions from the std namespace.

If you have to use the «name.h» headers for some reasons (it's deprecated, see above), I would suggest to use the declarations and definitions from the global namespace.

In other words: prefer

#include <cstdio>

int main() {
std::printf("Hello world\n");
}

over

#include <stdio.h>

int main() {
printf("Hello world\n");
}

Where is getchar() besides cstdio?

The answer is that one of your other header files is also including <cstdio> or it's equivalent (I would guess <iostream>).

Including <cstdio> is the right thing to do. If you don't then you might find that your code stops compiling when it's used with a different compiler.

BTW header files are not libraries, and the definitive references for what is found in which header file are the C++ and C standards documents.

Also BTW this kind of experimentation is exactly the sort of thing you should be doing as a new C++ programmer.

Why do both std::printf and printf compile when using cstdio rather than stdio.h in C++?

The standard permits the compiler to also inject the names into the global namespace.

One reason for this is that it permits the implementation of <cstdio> to be:

#include <stdio.h>

namespace std
{
using ::printf;
using ::fopen;
// etc.
}

so the compiler/library vendor does not have to write and maintain so much code.

In your own code, always use std:: or using namespace std; etc. so that your code is portable to compilers which do not inject the names into global namespace.



Related Topics



Leave a reply



Submit