我们用C语言编写程序时,经常会用到“scanf”、“printf”等函数,这可是经典的输入输出函数。在Win上编程时会用到,在Linux上编程时会用到,在Mac上编程也会用到。你看,在这么多系统平台上都会用到C语言的“scanf”、“printf”函数,你有没有想过为啥它们不需要做任何修改就能用了?通吃大部分的平台啊!
因为“scanf”、“printf”等函数属于I/O函数,是C语言标准函数库的一部分。本文就来和你聊聊标准函数库的“标准”到底标准在哪里?
走起!
一、什么是标准函数库
“标准函数库”= “函数库” + “标准”。我们先来说说“函数库”。
1、 什么是函数库?
我很喜欢逛超市,很喜欢沉浸在超市琳琅满目的商品中,别问我为什么有这癖好,因为小时候太穷,没见过这么多好吃的!逛着逛着我经常会看到超市里面的商品仓库,里面有很多的进货商品。超市货架上什么东西快卖光了,工作人员就会从仓库里及时取出补货。
C语言中的函数库,其实不仅仅是C语言啦,好多编程语言的函数库差不多也是仓库的意思。只不过这个仓库里的商品都是“函数”:我们常见的scanf函数、printf函数、strcpy函数、strcat函数;abs函数、sin函数等,都放在这个函数库里。我们可爱的程序员GG和程序员MM,把我们编程中经常要用到的功能编写出一个个函数,最终都放进这个函数库供我们使用,是不是很感动!
虽然C语言的函数库包含着众多的可爱的函数,但是这些函数可不是无序的一盘散沙哦,而是被分成一个个的子库。比如:
- 专门用于C程序输入输出的函数子库。如scanf、printf、getchar、putchar等函数,把它们组织起来就是I/O函数子库;
- 专门处理C程序字符串的函数子库。如strcpy、strcat等函数,把它们组织起来就是字符串函数子库;
- 专门处理数学运算的函数子库。如fabs、asin等函数,把它们组织起来就是数学函数子库;
- 还有什么专门处理日期时间的函数子库、通用工具的函数子库等。有兴趣的同学可以网上搜一把。
2、 什么是标准的函数库?
我平时编程的系统平台有Win和Linux。我在Win上编写一个C程序代码,如下:
#include
int main(void)
{
int para = 0;
scanf("%d", ¶);
printf("=== %d ===", para);
return 0;
}
其中用到了scanf函数和printf函数,在Win上运行没问题。
这段C程序代码拿到Linux上运行,scanf函数和printf函数依然正常运行。也就是说scanf函数和printf函数可以在Win和Linux上不需要做任何改变即可正常运行,这就是通用的意思,换个说法就是标准的意思,非常的标准。下面我们会进一步展开分析。
如果这段C程序代码放在MAC上运行呢?这。。。我放下吃了三天的泡面,抹了一把辛酸泪,仰天长叹:”这辈子一定要攒够钱买一台MAC“!
二、进一步解释“标准”
要更深入地解释C语言标准函数库的”标准“含义,就要说到”系统级别函数“、”系统API“的话题了。
1、 系统级别函数
像Win、Linux等操作系统,它们本身会提供N多个函数供外部的第三方应用程序调用,也就是说操作系统开发商自己会写一些函数,这些函数属于操作系统的一部分。
假设Win操作系统自己提供了一个函数叫做:readWin,这个函数专门用于从键盘读入数据的。假设现在Linux操作系统自己也提供了一个函数叫做:readLin,这个函数也是专门用于从键盘读入数据的。readWin和readLin功能是一样的,但它们内部具体实现,Win和Linux是不一样的。
例如下图以Linux为例,假设它有三个系统级别函数,分别是readLin、openLin、writeLin,各自实现对文件的读取、打开和写入操作。
Linux系统级别函数示意图
至于MAC。。。。我放下手中的泡面,又是一把辛酸泪!
2、 系统API
虽然说有了系统级别函数,我们自己编写的应用程序就可以调用它们来实现读取、写入等访问硬件的操作,但是Win系统和Linux系统的程序员觉得这种直接调用系统级别函数还是不够好,他们干脆把这些众多的系统级别函数又封装了下,形成了系统API。
API,全称是应用编程接口,其实也没什么玄乎的地方,说白了也是一个个的函数。也就是说,系统API的这些函数里面使用了系统级别函数,也可能没有使用系统级别函数。比如,win32 API的一系列函数内部调用了Win系统的系统级别函数。
假设Win系统有一个API叫做readAPI,它封装了Win的系统级别函数readWin;再假设Linux系统有一个API也叫做readAPI,它封装了Linux的系统级别函数readLin。那么上面那段C程序代码中的scanf函数只要调用这个readAPI,那么它就可以在Win上、Linux上不用做任何改变就可以正常运行。这里函数readAPI就是一个通用的标准的函数。
例如下图以Linux为例。假设它有两个系统API,分别是readAPI和writeAPI。前者调用了系统级别函数readLin和openLin;后者只是调用了系统级别writeLin。那么C语言标准函数库的函数只会调用readAPI和writeAPI,而不会直接调用readLin、openLin、writeLin。这样标准函数库不需要做修改就可以在Win上正常运行。
Linux系统API示意图
Win、Linux等操作系统的API函数为了都能成为这种通用的标准的函数,它们都遵循了POSIX标准。
3、 标准函数库的”标准“二字的理解
C语言标准函数库的”标准“二字,就在于函数库中的函数不使用系统级别函数还好,如果要使用系统级别函数,那么必须调用通用的标准的系统API。有点绕好像!
这么说吧:
- 标准函数库里如果有函数不需要使用系统级别函数,那么这些标准函数库的函数就没有标准不标准的概念,因为它们放到哪个系统上都可以不用做修改就能正常运行。为啥?因为它们就是不调用任何系统级别函数啊,自成一体,随便放哪儿都能跑!
- 标准函数库里如果有函数需要与底层的硬件打交道,那么这些标准函数库的函数实现不会去直接调用系统级别函数,而是会调用系统通用的标准的API。比如这些函数调用了上面所说的通用的标准的系统API:readAPI,那么这些函数放在哪个系统上都不需要做任何修改就能正常地访问硬件,读取数据!
所以,所谓的C语言标准函数库的”标准“,就是调用了系统通用的标准的API的意思。
三、一个简单的示例
还以上面的那段C程序代码为例:
#include
int main(void)
{
int para = 0;
scanf("%d", ¶);
printf("=== %d ===", para);
return 0;
}
在Win上的运行结果如下:
在Linux上的运行结果如下:
这段C程序代码中的scanf函数和printf函数分别从键盘读入数据、向屏幕输出数据。
Win系统与Linux系统从键盘读入数据、向屏幕输出数据的系统级别函数的实现是不一样的,但是它们均提供了通用的标准的系统API,scanf函数与printf函数均调用了这个通用的标准的系统API,因此这份C程序代码未做任何修改就可以在两个平台上正常运行。因此scanf函数与printf函数是标准的IO函数!
四、库函数又是如何做到非标准?
C语言中有标准的函数库,那么肯定也有非标准的函数库。那么请你思考下,非标准的函数库的”非标准“三个字又该如何理解呢?欢迎在评论区留言!