By DeiDei


2015-09-16 10:26:51 8 Comments

C is somewhat, not exactly, a subset of C++. So we can use most of the C functions/headers in C++ by changing the name a little bit (stdio.h to cstdio, stdlib.h to cstdlib).

My question is actually kind of semantic. In C++ code (using newest version of GCC compiler), I can call printf("Hello world!); and std::printf("Hello world!); and it works exactly the same. And in the reference I am using it also appears as std::printf("Hello world!);.

My question is, is it preferred to use std::printf(); in C++? Is there a difference?

8 comments

@sergej 2015-09-16 10:39:10

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");
}

@M.M 2016-03-16 21:30:58

N3242 is not any C++ standard. N3337 the draft with fewest differences from C++11.

@jww 2017-03-08 13:01:15

Also see Jonathan Wakely's Why < cstdlib > is more complicated than you might think from the Red hat blogs. He details a number of problems from a C++ standard library implementer's perspective. He also provides a history going back to C++98.

@jww 2017-03-08 13:08:38

@sergej - Would you happen to know the C++03 treatment on the subject? Or is it hit or miss what will happen?

@Sjoerd 2017-03-25 03:14:22

<name.h> might be deprecated, there is no chance they will get removed anytime soon. Quite the opposite, in fact. There is a proposal to remove the deprecated label, see open-std.org/JTC1/SC22/WG21/docs/papers/2017/p0619r0.html#3.‌​5 . "Finally, it seems clear that the C headers will be retained essentially forever, as a vital compatibility layer with C and POSIX. It may be worth undeprecating the headers, [..]"

@eiennohito 2015-09-17 14:16:22

From my own practice: use std:: prefixes. Otherwise one day abs will bite you very painfully in case you using floating points.

Non-qualified abs refers to function defined on int on some platforms. On others it is overloaded. However std::abs is always overloaded for all types.

@anukul 2015-09-16 10:40:56

In stdio

This is the C++ version of the Standard C Library header @c stdio.h, and its contents are (mostly) the same as that header, but are all contained in the namespace @c std (except for names which are defined as macros in C).

So it should not make any difference.

@jalf 2015-09-16 10:39:03

No, you're fine either way.

The original intent was that the <___.h> headers would be the C versions which put everything in the global namespace, and the <c___> headers would be the C++-ified versions, which place everything in the std namespace.

In practice, though, the C++ versions also put everything into the global namespace. And there's no clear consensus that using the std:: versions is "the right thing to do".

So basically, use whichever you prefer. The most common is probably to use the C standard library functions in the global namespace (printf instead of std::printf), but there's not much reason to consider one "better" than the other.

@Miles Rout 2015-09-21 23:06:22

"And there's no clear consensus that using the std:: versions is "the right thing to do"." Uh, yes there absolutely is consensus that that is the right thing to do.

@Jeremy Friesner 2015-09-22 03:15:21

How does one objectively determine whether or not consensus has been reached?

@jalf 2015-09-22 07:32:01

@JeremyFriesner you post about it on SO and see if you get disagreeing comments. :)

@DevSolar 2015-09-22 15:08:46

@JeremyFriesner: The standard does not guarantee the C++ header versions put the identifiers in the global namespace. The standard also deprecates the C header versions. That looks pretty consensus to me. ;-)

@jalf 2015-09-22 15:45:52

@DevSolar look the word "consensus" up in a dictionary, then. It is not about what the standard says, but what C++ programmers say -- and especially, what they do. There's a reason that literally every standard library implementation provides the C headers, and have the C++ headers put everything in the global namespace as well. :)

@DevSolar 2015-09-22 16:28:58

@jalf: Let's say the committee achieved consensus, then. And it's not about what the programmers do, it's what the compiler and library maintainers do. ;-)

@Sjoerd 2017-03-25 03:22:33

@DevSolar FYI, recently - more than a year after your comment - this proposal has reached the committee: open-std.org/JTC1/SC22/WG21/docs/papers/2017/p0619r0.html#3.‌​5 "Finally, it seems clear that the C headers will be retained essentially forever, as a vital compatibility layer with C and POSIX. It may be worth undeprecating the headers, [..]"

@NeonMercury 2015-09-16 10:38:46

From the C++11 standard:

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).

So, if you use <cstdio>, you can be sure, that printf will be in the namespace std, and hence not in global namespace.
Using a global namespace creates a conflict of names. This is not C++ way.

Therefore, I'm using <cstdio> headers and advise you to do so.

@wjl 2015-09-17 15:56:20

Although I wish it worked this way, this is not true. If you include <cstdio> you are guaranteed that std::printf will exist, but there is no guarantee from the standard if ::printf will or will not exist as well. In fact, in every compiler I've ever heard of ::printf is injected into the global namespace when you include <cstdio>.

@syntagma 2015-09-16 10:38:11

The only difference there is is that in std::printf() by adding std:: scope resolution you will secure yourself from someone writing a function with the same name in the future, which would lead to namespace conflict. Both usages will lead to exactly the same OS API calls (you can check it under Linux by running strace your_program).

I find it very unlikely that someone would name a function like that, as printf() is one of the most commonly used functions out there. Also, in C++, iostreams are preffered over calls to cstdio functions like printf.

@Konrad Rudolph 2015-09-16 10:50:07

On the contrary, I find it quite likely: printf is sorely broken in C++ due to its lack of strong typing, replacing it with a better version is quite natural.

@Alice 2015-09-16 12:30:52

@KonradRudolph You can find it that way if you like, but you'd be wrong; it isn't meant to have strong typing, and there are many problems that cannot be solved with the required strong typing easily. That's why many comparable C++ solutions are much slower than printf. If you want to replace it with a "better" version, you are breaking the contract between language and programmer, and are in a state of sin to begin with.

@Konrad Rudolph 2015-09-16 12:33:15

@Alice Uhm, I’m not breaking any contract: std::printf is different from mynamespace::printf, and C++ explicitly allows me to define my own functions whose names shadow those from functions inside std. That’s simply not debatable. As for your claims that printf is efficient because of loose typing, that’s of course also wrong. printf isn’t even particularly efficient, there are many more efficient implementations that are strongly typed.

@Alice 2015-09-16 12:34:43

@KonradRudolph Absolutely incorrect; you are breaking the contract, written in the standard, that printf without any quantifiers applies distinctly to a C construct. Your usage of a namespace, aliasing the global namespace, is not a good idea. That's simply not debatable.

@Konrad Rudolph 2015-09-16 12:36:00

@Alice Can you please cite the standard on this? I’m not aware of any such verbiage.

@Ben Voigt 2015-09-17 20:35:56

@Konrad: It's POSIX that reserves printf in the global namespace, and not only if certain headers are included (this makes sense, since headers are permitted to include each other): pubs.opengroup.org/onlinepubs/9699919799/functions/…

@T.C. 2015-09-16 10:35:38

<cmeow> always provides ::std::purr and may or may not provide ::purr.

<meow.h> always provides ::purr and may or may not provide ::std::purr.

Use the form that is guaranteed to be provided by the header you include.

@nwp 2015-09-17 12:17:13

STL in poor disguise?

@T.C. 2015-09-17 16:54:48

@nwp nope. (15 chars)

@Jonathan Mee 2016-05-02 15:58:54

@T.C. If only the people who invented Foo and Bar were as creative as you...

@L. F. 2018-10-04 07:57:00

@T.C. Unfortunately, as I tried on my compiler, neither <cmeow> nor <meow.h> provides neither ::std::purr nor ::purr but rather a pre-processor error. Only <cstdio> and/or <stdio.h> provides ::std::printf and/or ::printf. :P

@Lundin 2018-10-05 07:52:05

@L.F. You might need strcat to produce ::purr.

@L. F. 2018-10-05 09:11:41

@Lundin You are even more humorous than T.C. :P

@razvan 2015-09-16 10:33:20

Using just printf without std:: could generate some name conflicts and is considered a bad practice by a lot of c++ devs. Google is your friend on this one, but here are some links, hope this helps

Why is "using namespace std" considered bad practice? http://www.cplusplus.com/forum/beginner/61121/

@syntagma 2015-09-16 10:34:27

using namespace std is a bad practice but using printf without std:: qualifier is not.

@DeiDei 2015-09-16 10:35:13

using namespace std; is not my problem here. I never use it. printf(); and std::printf(); work in C++ without using namespace std; That's why I posted the question.

@Konrad Rudolph 2015-09-16 10:35:24

@REACHUS Disagree. There’s no difference between the two scenarios.

@trenki 2015-09-16 10:36:26

I would never use std::printf it feels just plain odd.

@syntagma 2015-09-16 10:43:59

@KonradRudolph I didn't say there is a difference, I just expressed my opinion (see my answer for more rationale).

@Alice 2015-09-16 12:33:26

@KonradRudolph There is ABSOLUTELY a difference between the two; if you include the proper header, printf is guaranteed to exist without std::, by the standard. This doesn't squash anyone else's namespaces, doesn't do any of the nastiness that using namespace std does. The two are completely different, and to assert any equivalence is intellectually dishonest.

@Konrad Rudolph 2015-09-16 12:34:26

@Alice By “proper header” you presumably mean stdio.h. Sure. But the question was about cstdio, and (implicity) whether having global names is a problem (referred to in this answer). You seem incredibly hostile towards me. Have I stepped on your toes elsewhere?

@Davislor 2015-09-16 12:49:23

There is the minor concern that, if you import everything into the global namespace, you have no idea what names <stdio.h> might declare in the future. In practice, though, the standards committee is going to try to avoid breaking C code, and most implementations declare the C library symbols in the global namespace too.

@mindriot 2015-09-16 15:41:49

In any case, if you really must write printf instead of std::printf, use using std::printf rather than pulling in the whole namespace. And even then, avoid the using statement at :: level within any of your header files, because you still end up polluting the namespace of the person including your header.

Related Questions

Sponsored Content

18 Answered Questions

[SOLVED] Why should C++ programmers minimize use of 'new'?

24 Answered Questions

[SOLVED] When should you use a class vs a struct in C++?

  • 2008-09-10 16:29:54
  • Alan Hinchcliffe
  • 351727 View
  • 813 Score
  • 24 Answer
  • Tags:   c++ oop class struct ooad

8 Answered Questions

6 Answered Questions

[SOLVED] What is std::move(), and when should it be used?

23 Answered Questions

[SOLVED] Why do we need virtual functions in C++?

13 Answered Questions

[SOLVED] What is a smart pointer and when should I use one?

35 Answered Questions

[SOLVED] Why is "using namespace std" considered bad practice?

10 Answered Questions

0 Answered Questions

How non standard c headers (unistd.h, fcntl.h, ...) work with c++

3 Answered Questions

[SOLVED] c++ global namespace compile problems

Sponsored Content