122

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?

Jonathan Cast
  • 4,569
  • 19
  • 34
DeiDei
  • 10,205
  • 6
  • 55
  • 80
  • I doubt that there is a difference. It seems that printf() is just included in the **std** namespace but based on what cppreference describes it still requires `cstdio`. You just need to take care of the namespaces (or absence of). – rbaleksandar Sep 16 '15 at 10:35
  • 18
    In the event that one day they mandate the dumping of `C` library symbols into the global namespace be illegal I prefer using the `std::` qualifies versions. (Plus I kind of wish they had made it illegal). – Galik Sep 16 '15 at 10:37
  • 3
    @Galik: Agreed. That would safe a lot of stupid questions about C issues using a C++ compiler. – too honest for this site Sep 16 '15 at 11:03
  • 8
    There is no "a little bit pregnant". Either C is a subset, or it is not. Fact is, it is **not**. That is the reason the C headers have to be modified to work in C++. – too honest for this site Sep 16 '15 at 11:05
  • 2
    "almost all" is a pretty useless measure when talking about a set of uncountable many elements. By the same argument you could probably relate C and Java. – Daniel Jour Sep 16 '15 at 12:34
  • Notice that `std::abs` is not the same as `::abs`. It has many overloads for different types. – Brice M. Dempsey Sep 16 '15 at 17:32
  • 9
    @sasauke no, it's not a subset. C and C++ definitely **share** a subset, but C itself **is not** a subset of C++. – The Paramagnetic Croissant Sep 16 '15 at 18:45
  • “…it also appears as `std::printf("Hello world!);`” Have you made a typo here? That looks the same as the second usage example in the previous sentence. – bdesham Sep 16 '15 at 21:09
  • AFAIK it's the same because all examples you provided will yield a parsing error. You probably meant `"Hello world!"` instead of `"Hello world!` (no ending double quote). – Bakuriu Sep 17 '15 at 05:56
  • @Olaf It would be more correct to say that C is *almost* a subset of C++. (As opposed to: *somewhat* a subset of C++) – user253751 Sep 17 '15 at 13:08
  • 2
    @immibis: No I used that term intentionally. Some constructs with identical syntax have different semantics in C and C++ and others are strongly recommended/required in C, while not possible in C++, like casting `void *` to other pointers (see the C standard). "almost" would imply there are just some minor changes required, which is actually not true. – too honest for this site Sep 17 '15 at 13:18

9 Answers9

115

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");
}
sergej
  • 17,147
  • 6
  • 52
  • 89
  • 1
    N3242 is not any C++ standard. N3337 the draft with fewest differences from C++11. – M.M Mar 16 '16 at 21:30
  • 3
    Also see Jonathan Wakely's [Why < cstdlib > is more complicated than you might think](https://developers.redhat.com/blog/2016/02/29/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 Mar 08 '17 at 13:01
  • @sergej - Would you happen to know the C++03 treatment on the subject? Or is it hit or miss what will happen? – jww Mar 08 '17 at 13:08
  • 7
    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 http://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, [..]"* – Sjoerd Mar 25 '17 at 03:14
  • 1
    @Sjoerd Interesting. Updated proposal: – alx - recommends codidact Jul 08 '21 at 10:20
85

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

T.C.
  • 133,968
  • 17
  • 288
  • 421
9

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.

jalf
  • 243,077
  • 51
  • 345
  • 550
  • 2
    "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. – Miles Rout Sep 21 '15 at 23:06
  • 4
    How does one objectively determine whether or not consensus has been reached? – Jeremy Friesner Sep 22 '15 at 03:15
  • 10
    @JeremyFriesner you post about it on SO and see if you get disagreeing comments. :) – jalf Sep 22 '15 at 07:32
  • 1
    @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. ;-) – DevSolar Sep 22 '15 at 15:08
  • 2
    @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. :) – jalf Sep 22 '15 at 15:45
  • @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. ;-) – DevSolar Sep 22 '15 at 16:28
  • 2
    @DevSolar FYI, recently - more than a year after your comment - this proposal has reached the committee: http://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, [..]"* – Sjoerd Mar 25 '17 at 03:22
  • 1
    Given that the standard removed the status of deprecated, I'll say that the global-namespaced identifiers are _better_ (except maybe for the case of overloads, such as `abs(3)`/`std::abs()`, in which case be careful), as there's less clutter, and everyone knows where `printf(3)` comes from. – alx - recommends codidact Jul 08 '21 at 11:42
3

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.

syntagma
  • 23,346
  • 16
  • 78
  • 134
  • 1
    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. – Konrad Rudolph Sep 16 '15 at 10:50
  • 1
    @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. – Alice Sep 16 '15 at 12:30
  • 1
    @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. – Konrad Rudolph Sep 16 '15 at 12:33
  • @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_. – Alice Sep 16 '15 at 12:34
  • 5
    @Alice Can you please cite the standard on this? I’m not aware of any such verbiage. – Konrad Rudolph Sep 16 '15 at 12:36
  • @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): http://pubs.opengroup.org/onlinepubs/9699919799/functions/V2_chap02.html#tag_15_02_02 – Ben Voigt Sep 17 '15 at 20:35
3

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.

  • 5
    Although I wish it worked this way, this is not true. If you include `` 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 ``. – wjl Sep 17 '15 at 15:56
3

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.

eiennohito
  • 158
  • 7
2

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/

Community
  • 1
  • 1
razvan
  • 355
  • 4
  • 19
  • 5
    `using namespace std` is a bad practice but using `printf` without `std::` qualifier is not. – syntagma Sep 16 '15 at 10:34
  • `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. – DeiDei Sep 16 '15 at 10:35
  • @REACHUS Disagree. There’s no difference between the two scenarios. – Konrad Rudolph Sep 16 '15 at 10:35
  • I would never use `std::printf` it feels just plain odd. – trenki Sep 16 '15 at 10:36
  • @KonradRudolph I didn't say there is a difference, I just expressed my opinion (see my answer for more rationale). – syntagma Sep 16 '15 at 10:43
  • @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. – Alice Sep 16 '15 at 12:33
  • @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? – Konrad Rudolph Sep 16 '15 at 12:34
  • There is the minor concern that, if you import everything into the global namespace, you have no idea what names `` 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. – Davislor Sep 16 '15 at 12: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. – mindriot Sep 16 '15 at 15:41
2

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.

anukul
  • 1,922
  • 1
  • 19
  • 37
-1

First of all, printf is a well-known function in the C library, and almost nobody would like to name a function as printf.

Second, in the header file <cstdio>, printf is both in the std namespace and the global namespace. So writing std:: prefix or not just work the same.

In my opinion, If your code and the library you use do not contain any printf in other namespaces. Just simply use printf, at least you can save your time from typing std::. Or better use std::printf to avoid any possible name conflicts. std::printf is safer. printf is more convenient.

user16217248
  • 3,119
  • 19
  • 19
  • 37
Charile C
  • 1
  • 1
  • As it’s currently written, your answer is unclear. Please [edit] to add additional details that will help others understand how this addresses the question asked. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – Community May 04 '23 at 13:40