stdio.h及cstdio的区别
2013-07-04 16:45:19
找了很多资料,没有说的很明白的,下面是老外的一篇文章,解释的比较清楚,后面给出翻译。
Clarifying stdio.h versus cstdio
转自:http://forums.codeguru.com/showthread.php?344430-Clarifying-stdio-h-versus-cstdio
I constantly see recommendations to #include <cstdio> 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 <cstdio>代替 #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
小结:
- 在C++下,若要使用C中已有库中的函数如stdio,文件包含方式为前面加一个c,同时去掉.h后缀,如#include <cstdio>,同时必须加上using namaspace;对于其他类似的函数同样;
- 对于C++特有的库,直接用去掉.h后缀的文件包含,并加上using namaspace;
VS2010下实例分析:
针对上面的讨论,在VS2010下,用一段小代码测试
在C++中,若要使用printf,我们知道该函数在C中是在stdio中包含的
文件包含写法1(标准C++风格,推荐):
对于C++,标准的写法如下
#include <cstdio>
using namespace std; int main()
{
int a = ; printf("%d\n",a); return ;
}
编译,没有waring,没有error,运行可正确输出。
文件包含写法2(旧式C风格,不推荐,且在VS2010下编译出错):
C标准的写法,如下:
#include <stdio.h>
但是在VS2010下编译,会报错找不到该头文件:Cannot open include file: 'cstdio.h': No such file or directory
疑问:根据上面的解释,虽然写的是C++的代码,但是这样写也可以,是标准支持的,只不过标准推荐用第一种写法。此处为何编译出错,原因未知???
文件包含写法3(错误的写法,但是大多数编译器不活给出waring或error,仍可编译通过,在以后的编译器下可能会出错,强烈不推荐):
但如果文件包含去掉using namespace std;,即写成:
#include <cstdio>
编译,运行结果与文件包含写法1完全一样,没有任何warning。这就是上面所说的许多编译器不能完全正确地实施这个规则,在使用新的header时,将所有的名字放入两个namespace。在以后的编译器下可能会出错
疑问:使用printf函数,包含iostream也可以???
我们知道printf对于C而言,是包含在stdio中的,对于C++则是在cstdio中的,但是奇怪的是,我在VS2010下,只包含iostream,如下:
#include <iostream>
居然也可正确编译、运行,原因未知,可能还是类似于文件包含写法3的原因,编译器没有很好的处理C与C++的文件包含问题。
在iostream中并没有包含printf函数,为何可正确使用printf???
同样地,写成
#include <iostream>
using namespace std;
但是,若要使用cout、cin等iostraem中真正包含的函数,就必须加上using namespace std;的声明,而不能只写#include <iostream>,如下:
#include <iostream>
//using namespace std; int main()
{
int a = ; //printf("%d\n",a);
cout<<a<<endl;
return ;
}
会提示没有声明cout、endl:error C2065: 'cout' : undeclared identifier
C++头文件包含何时要加.h,何时不加.h,何时在前面加c?
C++中不要#include <iostream.h>,不要#include <string.h>,因为它们已经被C++标准明确的废弃了,请改为 #include <iostream> 和 #include <cstring>.规则就是:
a. 如果这个头文件是旧C++特有的,那么去掉 h后缀,并放入std名字空间,
比如 iostream.h 变为 iostream.
因此,若要使用iostream库中函数,文件包含为
#include <iostream>
using namespace std;
若只写#include <iostream>,而没有using namespace std;,会报错:error C2065: 'cout' : undeclared identifier,因为cout是在std中命名的,必须加上using namespace std;
可能在早期的编译器中,也支持#include <iostream.h>,可不用写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/
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.
下面来自百度百科:
下面参考:http://no001.blog.51cto.com/1142339/1065812
在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
stdio.h及cstdio的区别的更多相关文章
- stdio.h cstdio的区别
stdio.h cstdio string.h cstring math.h cmath .h是c语言的习惯,在c++中,替换为在前面加个c
- C++中vector小学习,顺便查了下<stdio.h>(或<cstdio>)
今天看书,邻桌在看<C++ Primer>,拿过来看了一会儿.以前比较少用vector容器,看了下后,瞬间觉得好腻害的样子,就想试一下.嗯,就是试一下而已.(代码可能网上都差不多,有参考) ...
- include<stdio.h> 和include<iostream.h>的区别
stdio 是C标准库里面的函数库 对应的基本都是标准输入输出等等C语言常用库的定义iostream是C++标准库的头定义, 对应的基本上是C++的输入输出相关库定义开发C程序用Stdio, C++用 ...
- iostream.h 和stdio.h区别
stdio.h是C的标准I/O库,是以函数的方式向buffer写入或读取字符.输入输出是这样的printf(...);,scanf(...); iostream是C++的标准I/O库,引入了输入/输出 ...
- 学习第一个头文件stdio.h
使用标准输入输出库函数时要用到 “stdio.h”文件,因此源文件开头应有以下预编译命令: #include<stdio.h> stdio是standard input&outup ...
- #include <stdio.h>
1 fflush 2 fgetc 3 fgets 4 fprintf 5 fputc 6 fputs 7 fscanf 8 fseek 9 ftell 10 perror 11 remove 12 r ...
- 走进C标准库(2)——"stdio.h"中的fopen函数
其他的库文件看起来没有什么实现层面的知识可以探究的,所以,直接来看stdio.h. 1.茶余饭后的杂谈,有趣的历史 在过去的几十年中,独立于设备的输入输出模型得到了飞速的发展,标准C从这个改善的模型中 ...
- 基于函数的I/O操作(头文件stdio.h)
基于函数库的I/O是C语言标准库的功能,基于系统级I/O函数实现. 系统级I/O函数对文件的标识是文件描述符,C语言标准库中对文件的标识是指向FILE结构的指针.在头文件cstdio或stdio.h中 ...
- 逆向 stdio.h 函数库 fwrite 函数(调试版本)
0x01 fwrite 函数 函数原型: size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream) 函数功能:把 ...
随机推荐
- [转]主键冲突的话就更新否则插入 (ON DUPLICATE KEY UPDATE )
mysql "ON DUPLICATE KEY UPDATE" 语法如果在INSERT语句末尾指定了ON DUPLICATE KEY UPDATE,并且插入行后会导致在一个UNIQ ...
- js文件内部导入引用js文件方法
function include(path){ var a=document.createElement("script"); a.type = "te ...
- html5学习笔记——2016/4
HTML5新增的结构元素: section article aside header hgroup footer nav figure HTML ...
- javascript 面向对象技术
面向对象术语 对象 ECMA-262 把对象(object)定义为“属性的无序集合,每个属性存放一个原始值.对象或函数”.严格来说,这意味着对象是无特定顺序的值的数组. 尽管 ECMAScript 如 ...
- phpcms常用接口调用方法
常用函数 , 打开include/global.func.php,下面存放一些公共函数 view plaincopy to clipboardprint?function str_charset($i ...
- 【python】开始python之旅
上午开始抽空学习python,具体内容如下: (1)安装了python 2.7 (2)安装了notepad ++,安装它之前,在notepad++和Sublime Text之间纠结了一下,baidu了 ...
- go语言使用protobuf
网上为什么充斥着大量几乎一模一样而且不正确的教程??? 妈的打开一个关于golang和protobuf的教程,无非都是protobuf多么多么牛逼,xml多么多么傻逼,然后就是怎么安装protobuf ...
- linux驱动系列之s3c2440内存布局
刚开始学习linux在2440上面 linux内核分配标志可以分为三类:行为修饰符.区修饰符.类型. 区修饰符表示从哪儿分配内存,内核把物理内存分为多个区,每个区用于不同的目的. 内存中缓冲区存在的原 ...
- ExtJs 4.2.1 点击按钮弹出表单的窗口
初学ExtJs,做项目的时候想做一个这样的效果:点击按钮弹出对话框,之前一直是使用EasyUi来做的, EasyUi里有Dialog,用起来很方便,但是现在转移到ExtJs上后,发现没有Dialog这 ...
- SQLSERVER数据库管理数据库原理
数据库的存储结构: 1.逻辑存储结构:是指数据库有那些性质的信息组成,即一个数据库由若干用户可视的各种数据库对象构成,如:表,视图,索引,存储过程等 2.物理存储结构:表现为存储数据的各类操作系 ...