鱼C论坛

 找回密码
 立即注册
查看: 1972|回复: 15

[已解决]看了甲鱼哥的视频_(:з」∠)_才有所感悟,但还是遇上问题了

[复制链接]
发表于 2018-9-14 18:02:39 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
QQ截图20180914175803.jpg

为啥我的输入会变成乱码………………
最佳答案
2018-9-14 22:50:30
彭尼玛 发表于 2018-9-14 22:21
哇,感动,学习到了2个东东_(:з」∠)_一个是#if #什么的,第一次知道还有这种用法,开心啊。
第二个, ...

GIF1.gif
GIF2.gif
GIF3.gif

图1没有输出 "hello world",因为fprintf不是直接把内容输出到显示器,而是先把内容输出到缓冲区,之后main函数直接返回了,返回到了启动代码,启动代码调用了main函数,main函数执行完后返回到启动代码
之后启动代码调用了exit函数退出了程序

图2输出了 "hello world",因为调用了 fflush(stdout);

图3也没有输出 "hello world"

实际上图1和图3都输出了东西只是输出的不一样而且也看不到,输出是在调用exit函数之后,输出后直接就结束程序了

当检测到stdout的缓冲区还有数据时,exit内部调用了类似 fflush(stdout);的函数,但是已经没机会显示出来了(又或者说是 显示出来了只是太快看不到而已)

我们的程序把main函数中的buf作为缓冲区,main函数返回后buf已经不存在了,这时调用的 fflush(stdout);函数会输出错误的数据
当buf是static的时候,意味着buf在整个程序的运行期间都是有效的,在main函数返回后也有效

在直接运行,不调试的情况下可以看到exit函数中调用类似 fflush(stdout);函数后输出的内容
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2018-9-14 22:09:22 | 显示全部楼层
1.png
2.png
3.png
#include <stdio.h>
#include <stdlib.h>

int main(void)
{
#if 0
        char buf[100];
        setvbuf(stdout, buf, _IOFBF, 100);
        fprintf(stdout, "hello world\n");
        //fflush(stdout);
#elif 0
        char buf[100];
        setvbuf(stdout, buf, _IOFBF, 100);
        fprintf(stdout, "hello world\n");
        fflush(stdout);
#else
        static char buf[100];
        setvbuf(stdout, buf, _IOFBF, 100);
        fprintf(stdout, "hello world\n");
        //fflush(stdout);
#endif
        return 0;
}
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2018-9-14 22:21:36 | 显示全部楼层

哇,感动,学习到了2个东东_(:з」∠)_一个是#if #什么的,第一次知道还有这种用法,开心啊。
第二个,想问,为什么申请了静态数组就阔以有这种操作了呢??
这个static 好漂亮,到底是啥原理
static 我记得是如果在块里的话就是静态局部无链接的变量。文件作用域。可是为啥会这样子捏??!!
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2018-9-14 22:50:30 | 显示全部楼层    本楼为最佳答案   
彭尼玛 发表于 2018-9-14 22:21
哇,感动,学习到了2个东东_(:з」∠)_一个是#if #什么的,第一次知道还有这种用法,开心啊。
第二个, ...

GIF1.gif
GIF2.gif
GIF3.gif

图1没有输出 "hello world",因为fprintf不是直接把内容输出到显示器,而是先把内容输出到缓冲区,之后main函数直接返回了,返回到了启动代码,启动代码调用了main函数,main函数执行完后返回到启动代码
之后启动代码调用了exit函数退出了程序

图2输出了 "hello world",因为调用了 fflush(stdout);

图3也没有输出 "hello world"

实际上图1和图3都输出了东西只是输出的不一样而且也看不到,输出是在调用exit函数之后,输出后直接就结束程序了

当检测到stdout的缓冲区还有数据时,exit内部调用了类似 fflush(stdout);的函数,但是已经没机会显示出来了(又或者说是 显示出来了只是太快看不到而已)

我们的程序把main函数中的buf作为缓冲区,main函数返回后buf已经不存在了,这时调用的 fflush(stdout);函数会输出错误的数据
当buf是static的时候,意味着buf在整个程序的运行期间都是有效的,在main函数返回后也有效

在直接运行,不调试的情况下可以看到exit函数中调用类似 fflush(stdout);函数后输出的内容
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2018-9-14 23:06:53 | 显示全部楼层
人造人 发表于 2018-9-14 22:50
图1没有输出 "hello world",因为fprintf不是直接把内容输出到显示器,而是先把内容输出到缓冲区 ...

太棒了,太棒了,简直太棒了,静态存储期的妙用居然竟然在这里有了体现,太棒了,
看得我简直太棒了!!!!非常感谢!!
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2018-9-14 23:12:50 | 显示全部楼层
人造人 发表于 2018-9-14 22:50
图1没有输出 "hello world",因为fprintf不是直接把内容输出到显示器,而是先把内容输出到缓冲区 ...

main函数返回到了启动代码,是不是就是你所说的exit内部?
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2018-9-14 23:18:00 | 显示全部楼层
人造人 发表于 2018-9-14 22:50
图1没有输出 "hello world",因为fprintf不是直接把内容输出到显示器,而是先把内容输出到缓冲区 ...

试着尝试去看了下stdio.h里面的东西,就调试进去,看不懂哪个才是类似fflush的东西,好懵逼啊,这特么是用C语言写的吗……完全看不懂
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2018-9-14 23:35:08 | 显示全部楼层
本帖最后由 人造人 于 2018-9-14 23:40 编辑
彭尼玛 发表于 2018-9-14 23:12
main函数返回到了启动代码,是不是就是你所说的exit内部?


操作系统加载了当前程序后先执行一段用来申请必要的资源、初始化运行环境的代码(我把这段代码称作 “启动代码”)运行环境初始化完成后调用main函数,如果main函数返回了,那就调用exit函数退出程序
也就是如果你在main函数中调用了exit函数那就直接退出程序了,不会返回到启动代码(释放资源的操作留给了exit函数),如果你的代码没有调用exit函数,那么返回到启动代码后,启动代码帮你调用exit函数

exit是一个函数,这个函数不仅你的代码可以调用,启动代码也可以调用
exit函数和启动代码是两回事
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2018-9-14 23:36:16 | 显示全部楼层
彭尼玛 发表于 2018-9-14 23:18
试着尝试去看了下stdio.h里面的东西,就调试进去,看不懂哪个才是类似fflush的东西,好懵逼啊,这特么是 ...

stdio.h文件中只是声明,exit函数的实现不在stdio.h中
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2018-9-14 23:40:02 | 显示全部楼层
1.png
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2018-9-15 09:03:25 | 显示全部楼层
人造人 发表于 2018-9-14 23:35
操作系统加载了当前程序后先执行一段用来申请必要的资源、初始化运行环境的代码(我把这段代码称作 “ ...

哦,明白了,启动代码是一开始就有的呀_(:з」∠)_明白了,按照你所说的我试着让buf缓冲区放到main外面和自己在内部添加exit(0)  两者皆成功让乱码显示出来。
也就是说启动代码本来是准备帮我们调用exit函数的,可是由于出了main函数这个块,属于局部自动变量的buf的数据清空了,所以这时候我们的输出会变成乱码是吧。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2018-9-15 11:32:00 | 显示全部楼层
彭尼玛 发表于 2018-9-15 09:03
哦,明白了,启动代码是一开始就有的呀_(:з」∠)_明白了,按照你所说的我试着让buf缓冲区放到main外面和 ...

想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2018-9-15 12:23:41 | 显示全部楼层

谢谢,最后一个问题,是不是不管什么情况下的程序只要我没有添加exit()函数,系统的启动代码都自动会在main函数结束之后调用这个exit函数帮我们进行退出?那retrun不是退出的吗?
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2018-9-15 12:37:55 | 显示全部楼层
彭尼玛 发表于 2018-9-15 12:23
谢谢,最后一个问题,是不是不管什么情况下的程序只要我没有添加exit()函数,系统的启动代码都自动会在ma ...

return 只是函数返回
main函数中的return也一样
main函数中的return会返回到启动代码
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2018-9-15 12:39:29 | 显示全部楼层
彭尼玛 发表于 2018-9-15 12:23
谢谢,最后一个问题,是不是不管什么情况下的程序只要我没有添加exit()函数,系统的启动代码都自动会在ma ...

每一个函数都可以有return,main函数也一样
return可以看成是退出当前函数
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2018-9-15 12:54:08 | 显示全部楼层
人造人 发表于 2018-9-15 12:39
每一个函数都可以有return,main函数也一样
return可以看成是退出当前函数

o o oo 明白了,明白了,谢谢谢谢_(:з」∠)_感动感动死了
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2024-11-30 09:47

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表