stdio.h及cstdio的区别

stdio.h及cstdio的区别转自 找了很多资料 没有说的很明白的 下面是老外的一篇文章 解释的比较清楚 后面给出翻译 Clarifyingst hversuscstdi 转自 http forums codeguru com showthread php Clarifying stdio h versus cstdioIconst

转自:http://www.cnblogs.com/youngforever/p/3172352.html

找了很多资料,没有说的很明白的,下面是老外的一篇文章,解释的比较清楚,后面给出翻译。

Clarifying stdio.h versus cstdio

转自:http://forums.codeguru.com/showthread.php?-Clarifying-stdio-h-versus-cstdio

I constantly see recommendations to #include

instead of using stdio.h and the same for the other C headers. What most posters fail to mention is that 
this should put all the symbols into namespace std and NOT into the global namespace.

This you have to write std::printf(…). Simply writing printf alone will not work .

The same applies to the headers :

cassert ciso646 csetjmp cstdio ctime cctype climits csignal cstdlib cwchar cerrno clocale cstdarg cstring cwctype cfloat cmath cstddef.

This is clearly defined by ISO 14882 in footnote 160:




 

The “.h” headers dump all their names into the global namespace, whereas the newer forms keep their names in namespace

std. Therefore, the newer forms are the preferred forms for all uses except for C++ programs which are intended to be strictly compatible
with C.





Most compilers completely fail to implement this correctly and put all the names into both namespaces when using the new headers. As this is incorrect behaviour, it is quite likely to change in the future which means that code you write now may break on newer compilers as they get closer to the standard.

 

As an aside note that many compilers fail to give even a warning (and even on the highest warning level) when you write void main(), even though the standard clearly dictates that main MUST return int.

Nathan Myers, a member of the C++ standards committee wrote this paper on header strategy here:http://www.cantrip.org/cheaders.html

Markus




 


大致翻译了一下,如下:

 

经常看到有建议说要使用 #include

代替  #include stdio.h,但很少有人提及这将把所有的symbol放进std namespace,而非 global namespace.这样,就
必须写成std::printf
(…)(注意是必须,但有的编译器却能通过,具体解释见下面),简单的写成printf是不行的。

这对于以下的有文件同样:cassert ciso646 csetjmp cstdio ctime cctype climits csignal cstdlib cwchar cerrno clocale cstdarg cstring cwctype cfloat cmath cstddef.
这在ISO 14882 in footnote 160:中有明确说明:




 

 

The “.h” headers dump all their names into the global namespace, whereas the newer forms keep their names in namespace

std. Therefore, the newer forms are the preferred forms for all uses except for C++ programs which are intended to be strictly compatible
with C.





 

也就是:”.h”头文件将所有名字放在global namespace中,在新的方式下(指的是诸如cstdio这样的头文件),名字是放在namespace std中的。因此,新的方式是所有应用推荐的方式,除非是要编写与C严格兼容的程序。

 

 

许多编译器不能完全正确地实施这个规则,在使用新的header时,将所有的名字放入两个namespace。但因为这是不正确的,所以在以后很可能会改变(编译器会有所优化),这意味着你现在写的代码在新的编译器上可能会出错,因为它们更接近于新的标准。




许多编译器连一个warning都不能给出(即使是在最高warning级别下),比如当你写一个void main()时,许多编译器都不会给出warning,即使标准明确指出main函数必须返回int型数据。

C++标准委员会的成员Nathan Myers写了一篇关于header strategy文章:http://www.cantrip.org/cheaders.html

小结:

  1. 在C++下,若要使用C中已有库中的函数如stdio,文件包含方式为前面加一个c,同时去掉.h后缀,如#include

    ,同时必须加上using namaspace;对于其他类似的函数同样;
  2. 对于C++特有的库,直接用去掉.h后缀的文件包含,并加上using namaspace;

VS2010下实例分析:

针对上面的讨论,在VS2010下,用一段小代码测试

在C++中,若要使用printf,我们知道该函数在C中是在stdio中包含的

文件包含写法1(标准C++风格,推荐):

对于C++,标准的写法如下

 

复制代码
 1 #include 
     
      2 
     using 
     namespace 
      std;  
      3 
      4 
     int 
      main()  
      5 
     {  
      6 
     int a = 
     16 
     ;  
      7 
      8 printf( 
     " 
     %d\n 
     " 
     ,a);  
      9 
     10 
     return 
     0 
     ;  
     11 } 
    
复制代码

编译,没有waring,没有error,运行可正确输出。

文件包含写法2(旧式C风格,不推荐,且在VS2010下编译出错):

C标准的写法,如下:

 

1 #include 
    

 

但是在VS2010下编译,会报错找不到该头文件:Cannot open include file: ‘cstdio.h’: No such file or directory

疑问:根据上面的解释,虽然写的是C++的代码,但是这样写也可以,是标准支持的,只不过标准推荐用第一种写法。此处为何编译出错,原因未知???

文件包含写法3(错误的写法,但是大多数编译器不活给出waring或error,仍可编译通过,在以后的编译器下可能会出错,强烈不推荐):

但如果文件包含去掉using namespace std;,即写成:

1 #include 
    

编译,运行结果与文件包含写法1完全一样,没有任何warning。这就是上面所说的许多编译器不能完全正确地实施这个规则,在使用新的header时,将所有的名字放入两个namespace。在以后的编译器下可能会出错

疑问:使用printf函数,包含iostream也可以???

我们知道printf对于C而言,是包含在stdio中的,对于C++则是在cstdio中的,但是奇怪的是,我在VS2010下,只包含iostream,如下:

 

1 #include 
    

 

 

 

居然也可正确编译、运行,原因未知,可能还是类似于文件包含写法3的原因,编译器没有很好的处理C与C++的文件包含问题。

在iostream中并没有包含printf函数,为何可正确使用printf???

同样地,写成

1 #include 
     
     2 
     using 
     namespace std; 
    

但是,若要使用cout、cin等iostraem中真正包含的函数,就必须加上using namespace std;的声明,而不能只写#include

,如下:

复制代码
 1 #include 
     
      2 
     // 
     using namespace std; 
      3 
      4 
     int 
      main()  
      5 
     {  
      6 
     int a = 
     16 
     ;  
      7 
      8 
     // 
     printf("%d\n",a); 
      9 cout< 
     
       endl; 
      10 
      return 
      0 
      ;  
      11 } 
      
    
复制代码


 

 

C++头文件包含何时要加.h,何时不加.h,何时在前面加c?

 

C++中不要#include

,不要#include

,因为它们已经被C++标准明确的废弃了,请改为 #include

和 #include

.规则就是:



 

    a. 如果这个头文件是旧C++特有的,那么去掉 h后缀,并放入std名字空间,

 

   比如 iostream.h 变为 iostream.

因此,若要使用iostream库中函数,文件包含为

#include

using namespace std;

若只写#include

,而没有using namespace std;,会报错:error C2065: ‘cout’ : undeclared identifier,因为cout是在std中命名的,必须加上using namespace std;

可能在早期的编译器中,也支持#include

,可不用写using namespace std,但用VS2010编译,会报错Cannot open include file: ‘iostream.h’: No such file or directory。

 

    b. 如果这个头文件是C也有的,那么去掉 h后缀,增加一个c前缀,比如 string.h

 

    变为 cstring;stdio.h 变为 cstdio, 等等


 

 

Cplusplus的网站:http://www.cplusplus.com/reference/cstdio/

 

C library to perform Input/Output operations

Input and Output operations can also be performed in C++ using the C Standard Input and Output Library (cstdio, known as stdio.h in the C language). This library uses what are called streams to operate with physical devices such as keyboards, printers, terminals or with any other type of files supported by the system. Streams are an abstraction to interact with these in an uniform way; All streams have similar properties independently of the individual characteristics of the physical media they are associated with.

 


下面来自百度百科:

cstdio是将stdio.h的内容用C++头文件的形式表示出来。stdio.h是C标准函数库中的头文件,即:standard buffered input&output。提供基本的文字的输入输出流操作(包括屏幕和文件等)。由于C语言并没有提供专用于文字输入输出的关键字,所以该库是最普遍的C语言程序加载库。
stdio.h是以往的C和C++的头文件,cstdio是标准C++(STL),且cstdio中的函数都是定义在一个名字空间std里面的,如果要调用这个名字空间的函数,必须得加std::或者在文件中声明use namespace std。

Visual Studio 2012 – Visual C++

定义在标准C库头stdio.h传统上定义的宏。
#if
#include
#undef clearerr
#undef feof
#undef ferror
#undef getc
#undef getchar
#undef putc
#undef putchar
namespace std {
using ::fclose;
using ::feof;
using ::ferror;
using ::fflush;
using ::fgetc;
using ::fgetpos;
using ::fgets;
using ::FILE;
using ::clearerr;
using ::fopen;
using ::fprintf;
using ::fpos_t;
using ::fputc;
using ::fputs;
using ::fread;
using ::freopen;
using ::fscanf;
using ::fseek;
using ::fsetpos;
using ::ftell;
using ::fwrite;
using ::getc;
using ::getchar;
using ::gets;
using ::perror;
using ::putc;
using ::putchar;
using ::printf;
using ::puts;
using ::remove;
using ::rename;
using ::rewind;
using ::scanf;
using ::setbuf;
using ::setvbuf;
using ::size_t;
using ::sprintf;
using ::sscanf;
using::tmpfile;
using ::tmpnam;
using ::ungetc;
using ::vfprintf;
using ::vprintf;
using ::vsprintf;
}
#endif

 

下面参考:http://no001.blog.51cto.com//

在C语言中,stdio.h 头文件是主要的。而在后来的C++语言中,C只是C++的一个子集,且C++中,已不推荐再用C的类库,但为了对已有代码的保护,还是对原来的头文件支持。

   cstdio是c++从C的stdio.h继承来的,在前面加C同时不要H后缀,在C++环境当然是选用前者,两者内容都一样,只是cstdio头文件中定义的名字被定义在命名空间std中。使用后者就会带来额外的负担,需要区分哪些是
标准库明是C++特有的,哪些是继承过来的!!所以在C++中要尽量避免C风格的出现!!

cstdio code:
// cstdio standard header


#pragma once
#ifndef _CSTDIO_




#define _CSTDIO_
#include

 <yvals.h>

#ifdef _STD_USING






#undef _STD_USING
  #include

 <stdio.h>


#define _STD_USING




#else 
#include

 <stdio.h>


#endif 




#define _HAS_CONVENTIONAL_CLIB    1




#define _IOBASE    _base


#define _IOPTR    _ptr


#define _IOCNT    _cnt

#ifndef RC_INVOKED






#if _GLOBAL_USING
_STD_BEGIN




using ::size_t; using ::fpos_t; using ::FILE;


using ::clearerr; using ::fclose; using ::feof;


using ::ferror; using ::fflush; using ::fgetc;


using ::fgetpos; using ::fgets; using ::fopen;


using ::fprintf; using ::fputc; using ::fputs;


using ::fread; using ::freopen; using ::fscanf;


using ::fseek; using ::fsetpos; using ::ftell;


using ::fwrite; using ::getc; using ::getchar;


using ::gets; using ::perror;


using ::putc; using ::putchar;


using ::printf; using ::puts; using ::remove;


using ::rename; using ::rewind; using ::scanf;


using ::setbuf; using ::setvbuf; using ::sprintf;


using ::sscanf; using ::tmpfile; using ::tmpnam;


using ::ungetc; using ::vfprintf; using ::vprintf;


using ::vsprintf;
_STD_END




#endif 


#endif 

#ifndef _Filet






#define _Filet    FILE


#endif 

#ifndef _FPOSOFF
 






 #define _FPOSOFF(fp)  ((long)(fp))


#endif 




#endif 








 

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/220408.html原文链接:https://javaforall.net

(0)
上一篇 2026年3月17日 下午8:33
下一篇 2026年3月17日 下午8:34


相关推荐

  • rootfs.bin_libhdfs

    rootfs.bin_libhdfs忘了到底前几年看的一篇什么busybox的教程,写的及其复杂,以至于让我这么久以来一直不敢再去碰这个东西,直到今天又再次有了这个需求,特来再搞一次,没想到不到俩小时,一次搞定,特将这过程记录下来,以后也好有个参考。1环境宿主机:Ubuntu18.04交叉编译工具链:aarch64-linux-gnu-gcc7.4.0目标机:Armv8i.MX8EVKboard2下载…

    2022年10月7日
    5
  • OpenClaw(原 Clawdbot/Moltbot)安装指南,一篇讲明白云部署vs本地部署

    OpenClaw(原 Clawdbot/Moltbot)安装指南,一篇讲明白云部署vs本地部署

    2026年3月13日
    2
  • JVM初探(一):jvm内存结构[通俗易懂]

    JVM初探(一):jvm内存结构[通俗易懂]一、概述我们知道java代码先编译为.class文件,然后再将.class文件交由jvm执行。在程序运行的这一过程中,jvm会将其管理的内存空间划分为不同的区域,这些区域各有各的用途,我们将其分为五

    2022年8月16日
    7
  • springboot+idea热部署(自动刷新)

    springboot+idea热部署(自动刷新)近来在使用idea做springboot的项目,但是发现每次修改之后我都需要重新将项目关闭再开启,这样比较繁琐,发现通过热部署的方式让我们可以一边修改我们的项目,然后在页面中直接通过刷新展示出来spring为开发者提供了一个名为spring-boot-devtools的模块来使SpringBoot应用支持热部署,提高开发者的开发效率,无需手动重启SpringBoot应用。devtool…

    2022年6月26日
    50
  • 统计xml文件中标记框的特性

    统计xml文件中标记框的特性

    2020年11月8日
    196
  • mongodb和mysql应用场景区别_mongodb和mysql有哪些区别「建议收藏」

    mongodb和mysql应用场景区别_mongodb和mysql有哪些区别「建议收藏」mongodb和mysql有哪些区别发布时间:2020-09-0109:15:48来源:亿速云阅读:64作者:小新小编给大家分享一下mongodb和mysql有哪些区别,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!区别分析:)MySQL是关系型数据库。优势:在不同的引擎上有不同的存储方式。查询语句是使用传统的sql语…

    2025年7月10日
    4

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号