首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 开发语言 > C语言 >

小弟我对printf执行过程目前的理解

2012-05-04 
我对printf执行过程目前的理解之前发了一个讨教 printf函数执行细节的帖子。好几位前辈给了我答案。都是集中

我对printf执行过程目前的理解
之前发了一个讨教 printf函数执行细节的帖子。
好几位前辈给了我答案。都是集中在(。。。)缺省格式的分析上的。
先感谢几位前辈。
我困惑的地方在于。计算机是怎么知道 printf函数就是把字符输出在终端??这个是我不明白的地方。
这么说吧:stdio.h里面声明了printf的原型:Cdecl_printf(........);
Cdecl跟栈有关系。
那么为什么编译器就知道这个函数是用来的在终端输出呢?
————————————————————————————————
想了一天 我自己给出了一个比较能说服自己的解释
那就是 
编译器很可能里面写清楚了:printf是用来往终端按格式输出字符的。并且详细说了操作过程。
假设真的是这样,那么源文件在编译阶段 编译器读取到printf这个函数,就解释成为一个“往终端输出字符”的行为
之后转换成对应的汇编语言。
————————————————————————————————
我还没找到佐证这个猜想的证据。希望看到此贴的前辈能指点一下,谢谢

[解决办法]
晕了,白打字了,没发出去。。。。
Printf是标准库函数,C标准已经规定了它的功能,如果你的编译器没实现这个功能,那它就是不支持C标准,功能上楼主没必要纠结
至于实现,C出来就是为了可移植的,标准库函数在不同平台上,使用方法就应该相同,但是,对于显示这块来说,不同平台上,方法是不同的,所以,Printf在不同平台上的实现是不同的
实现未必是C写的,也可能是汇编,可能调用操作系统的相应功能,也可能直接调用硬件,
至于楼主理解的在编译时直接把汇编代码植入进去,这也是不完全正确的,因为编译时有可能是直接把目标码放程序中,也可能是执行时动态链接,如果是动态链接,那编译时只是把入口点放进程序中而已,而不是整个实现
[解决办法]
这个东西如果说起来,就要说道汇编语言了
发一个自己实现的myprintf函数给你

void myprintf(char*,... );
int pow(int,int);

main()
{
myprintf("int is %d,%d,%d, char is %c",123,456,78901,'Q');
}

void myprintf(char *des, ...)
{
int desLength = 0;
int showpos = 0;
int param = 0;
int i = 0;
int iIndex =0;
while(des[i] != '\0')
{
desLength++;
i++;
}
i=0;
while(des[i] != '\0')
{
if(des[i]=='%')
{
if(des[i+1] == 'd')
{
int intValue = *(int *)(_BP + 6 + param*2);

int tempintValue = intValue;
int intLength = 0;
while(tempintValue/10 !=0)
{
intLength++;
tempintValue/=10;
}
intLength++;
for(iIndex=intLength; iIndex > 0; iIndex--)
{
int singalValue = intValue/pow(10,iIndex - 1);
*(char far *)(0xb8000000+160*10+80+showpos * 2) = 0x30 +singalValue;
*(char far *)(0xb8000000+160*10+81+showpos * 2) =2;
intValue = intValue - singalValue*pow(10,iIndex -1);
showpos++;
}
param++;
i+=2;

}
else if (des[i+1] == 'c')
{
*(char far *)(0xb8000000+160*10+80+showpos * 2) = *(int *)(_BP + 6 +param*2);
*(char far *)(0xb8000000+160*10+81+showpos * 2) =2;
i+=2;
showpos++;
param++;
}
else
{
*(char far *)(0xb8000000+160*10+80+showpos * 2) = *(char * )(*(int*)(_BP+4) +i);
*(char far *)(0xb8000000+160*10+81+showpos * 2) = 2;
i++;
showpos++;
}
}
else
{
*(char far *)(0xb8000000+160*10+80+showpos * 2) = *(char * )(*(int*)(_BP+4) +i);
*(char far *)(0xb8000000+160*10+81+showpos * 2) = 2;
i++;
showpos++;
}
}
}
int pow(int a, int b)
{
int result;
int i;
if(b==0)
{
result = 1;
}
else
{
result = a;
for(i=1;i<b;i++)
{
result = result * a;
}
}
return result;
}
[解决办法]
参看王爽的汇编语言综合研究 研究实验5,讲了c编译器是怎么实现printf函数的
[解决办法]
Cdecl是用来解决不定参数的调用的,跟LZ的问题无关。
编译器是不知道所谓终端这样的概念的。
终端这些都是操作系统提供的facility,printf只是调用sys call,sys call调用系统提供的机制,然后到终端,所以真想弄明白就去看系统的东西,而不是语言/编译器。

[解决办法]
printf会把你传入的buffer逐字节的格式化之后写入到FILE里的buffer,遇到\n或者buffer满就会将buffer write到磁盘,就这么简单。(这一段是说行缓冲的FILE)。

楼主先了解WINDOWS/LINUX的系统API,再结合printf的无缓冲,行缓冲,全缓冲就知道怎么实现的了,就是在系统API之上封装了一层buffer,按照语义在合适的实际发生实际磁盘操作。


[解决办法]
库函数实现时就是让printf做终端输出的,
至于要输出什么,主要取决于const char* format这个参数,
换句话说,printf("%c");这样调用也可以,但是结果是未定义的。
printf函数要输出什么完全取决于format字符串的指示,即使之后的
缺省参数没有给出,它也会想函数栈上读取,只是读取到值未定义。

热点排行