文章目录
注意
本文为针对C语言的基础技术向,更适合刚入门需要进阶的同学技术进阶使用,当然我会尽量用简单的语言让哪怕是初学者也可以看得懂,核心知识有如下部分:
- 变参函数的概念和使用
__attribute__(())
的概念和使用- printf函数的实现
视频
本文可以结合视频一起食用,效果更佳:视频链接
再观printf函数
相信绝大部分同学写的第一个程序,应该就是大名鼎鼎的Hello World
程序了,这个程序闻名于著名的《C语言程序设计(The C Programming Language)》(C语言之父丹尼斯·里奇(Dennis Ritchie)著)一书中,非常经典,以至于程序员们学习任何语言,都会先用这个语言运行个Hello World出来。
在C语言中,这个程序一般写出来是这个样子的:
#include <stdio.h>
int main()
{
printf("Hello World!\n");
return 0;
}
如果在命令行运行这个程序的话,你将获得一行Hello World!
输出。
如果你是一个不喜欢思考的初学者,可能会认为printf也许是C语言里面最基础最简单的函数了,毕竟这个程序这么简洁、格式这么规范、使用这么简单、甚至闭着眼睛都不会写错。
但如果我们往细究往深了想呢?printf它是如何实现的呢?我们是否可以实现一个自己的printf函数呢?为什么它会运行在命令行中而不是从屏幕某个规定的位置显示呢……
这时你可能会发现,woc,printf似乎比我们想象的要复杂太多了,你以为的简单小函数,其实却是个超级大boss。不过不要担心,我们会从基础开始讲,而且我会保证尽量说得简单明了。
print为什么要加个f
现在,我们重新抱着认真学习的态度来观察printf这个函数吧。首先我们从名字来解析一下。
我们知道,在英语中,print有打印、印刷的意思,这个词语完全可以解释将字符串打印到电脑屏幕上这个过程,那么为什么这个函数的名字要加上f呢?
其实这个f是format的缩写,即格式化的意思,printf其实为格式化打印的意思。那么格式化这个是怎么来的?
现在想想,如果我们希望在屏幕上输出一个变量该怎么做呢?最简单的方法就是使用格式字符,就如下面这个程序一样:
#include <stdio.h>
int main()
{
int a = 25;
printf("a = %d\n", a);
return 0;
}
这个函数将会在屏幕上输出一行a = 25
,在这个过程中%d就是变量a的格式符,它在字符串中占位,然后字符串在输出的时候,遇到了这个占位符,就会解析a的具体值,并把它转换为字符串的形式输出出来。
现在从这个功能中我们其实可以发现很多问题,我们来逐一解释:
格式符是什么时候被解析的?
这个问题是我在学习理解printf的时候第一个思考的问题,即格式符是如何什么时候被解析的,答案有两种,对应了两种不同的结果。
首先是在编译阶段被解析,这种方式的话也有两种情况,一是编译器有针对printf这类函数的优化,二是编译器会主动把字符串中的格式符变成某种执行效果。而另一种方案是printf函数内部实现的解析格式符。
我们可以用如下的程序来测试(为了方便,后面我们生成程序的名称都为demo.exe):
#include <stdio.h>
int main(int argc, char* argv[])
{