http://blog.chinaunix.net/u/6776/showart_186792.html C/C++深层探索
本末节我们概览一下C/C++标准库的全貌。
C/C++标准库的内容主要包括:
宏定义 (譬如: #define FLT_RADIX 2)
类型定义 (譬如: typedef unsigned wchar _t)
变量声明和定义 (譬如: extern int errno;)
库函数声明和定义 (譬如: size_t strlen(const char *s);)
此中,宏定义、类型定义、变量声明和库函数的声明都在标准头文件停止描述,所以,标准头文件实际上已经勾画出整个标准库的轮廓。
ostream queue set sstream
C90有这些:
assert.h ctype.h errno.h float.h
limits.h locale.h math.h setjmp.h
signal.h stdarg.h stddef.h stdio.h
stdlib.h string.h time.h
map memory new numeric
iso646.h wchar.h wctype.h
#ifdef __cplusplus
exception fstream functional iomanip
stdint.h tgmath.h
要注意的是,高版本的C标准不一定是仅仅增加了新的头文件,还可能对原先低版本C标准的某些头文件停止了修改和扩充。
至于C++的库(包括宏、类型和函数),直到C++标准出版前一直都是放在全局空间,这些C++头文件和普通的C头文件一样,均带有“.h”后缀,例如“iostream.h”。使用上和C语言没有什么不同:
/*C代码*/
#include<stdio.h>
int main()
{
extern “C” int yyy(); //同上
}
而对于C++,情况就有点复杂。
首先,C++的设计者希望C++能在相当大的程度上兼容C,至少,C++编译器应该最大限度的接受已经存在的大量C代码。所以,允许使用C标准库自然是追求的目标之一。但C语言并没有扩展名字这回事,也就是说,假如想间接使用已经用C编译器编译好的C库(主要是指库函数),C++编译器必须知道哪些是C库函数,从而差池其停止名字扩展。于是,链接修饰符extern “C”被用来指出哪些函数具有“C语言链接性质”,所以,编译器厂商一般都会在原来的C语言标准头文件增加一些东西:
#ifdef __cplusplus
extern “C” {
#endif
int xxx(); //C标准库函数的声明
...
...
climits clocale cmath csetjmp
//标准的C++代码:
#endif
根据是否定义宏“__cplusplus”决定是否添加“ extern “C” ”修饰符,假如宏被定义,则表明是C++编译器在处理代码,所以必须加上extern “C”;否则就不用添加,因为C编译器不认识extern “C”。
对C标准头文件作了以上处理后,我们就可以在C++代码中调用C库函数:
/*C++代码*/
#include<stdio.h>
int main(void)
{
printf(“calling printf in a cpp file\n”);
}
doctor异乡人 在std里定义的C库所对应的头文件都没有“.h”后缀,并且在前面多了一个字符“c”,下面是C++标准规定的C库头文件(注意,这里只有18个头文件,因为C99比C++标准晚推出,所以C++的C库只包露了C95的18个头文件):
//早期的C++代码:
#include<iostream.h>
extern int xxx(); //声明C库函数xxx()停止名字扩展
{
cout<<”using an old style head file”<<endl;
}
自然,C++编译器会对C++库函数停止名字扩展。
不过,C++标准出来后,情形就不一样了。标准规定,所有C/C++标准库都必须在名字空间std里停止定义,也就是说,标准保留出一个特定的名字空间,专门放置C/C++标准库,任何人都不应该在std定义自己的库。
使用C标准库很简单,只需要包露相应得头文件就可以了,例如:
cassert cctype cerrno cfloat
C99再增加下面这些:
int main(void)
cstdlib cstring ctime ciso646
#include<iostream>
同样,使用这些C++头文件必须声明使用std名字空间:
}
#include<cstdio>
using namespace std;
int yyy(); // 同上
ios iosfwd iostream istream
printf(“Don’t say me boring please.\n”);
}
大概:
{
#include<stdio>
std::printf(“Don’t say me boring please.\n”);
{
{
前者意味着可以间接使用已有的C库,后者则必须用C++编译器重新编译C库,g++采取了前者。
同样,在std里定义的C++库对应的头文件也没有“.h”后缀,以下是全部成员:
algorithm bitset complex deque
complex.h fenv.h initypes.h stdbool.h
{
iterator limits list locale
C95增加这几个:
而今我们来看看C语言的标准头文件。
stack stdexcept streambuf string
typeinfo utility valarray vector
而今,使用“C++标准版”的C库,必须明确声明使用std名字空间:
}
#include<iostream>
using namespace std;
csignal cstdarg cstddef cstdio
//标准的C++代码:
cout<<”Yes, you’re right...I am boring.”<<endl;
}
大概:
//标准的C++代码:
cwchar cwctype
int main(void)
{
std::cout<<”Last time, I swear!”<<endl;
}
最初,必定有一些喜好追问到底的读者会问:那些在名字空间std里面定义的C库函数究竟有没有停止名字扩展呢?
C++标准规定厂商可以自行决定是否扩展。就是说,C标准库既可以这样声明:
namespace std
int main(void)
extern “C” int xxx(); //声明C库函数xxx()不停止名字扩展
printf(“printf() again...boring!\n”);
...
//标准的C++代码:
也可以这样声明:
namespace std
{
int main(void)
extern int yyy(); //同上
int main(void)
}
}