- 论坛徽章:
- 0
|
看了精华区kenelxu关于缓冲区的那篇文章,仍有以下疑问!
原帖由 "albcamus"]kernelxu兄弟是不是comp.lang.c上的kernelxu?呵呵我不小心认出来了 [/quote 发表:
呵呵,这也被老大人出来了。不知老大在上面是什么马甲,能不能站内短信告知一下,以后说不定就“撞车”了。
自己有些东西也搞不清,就在comp.lang.c上发了一个贴。
大家也可以看一看别人的解答:
http://groups-beta.google.com/gr ... en#6b7dfa8b01784910
我将解答总结在下面,希望对大家理解setbuf()和setvbuf()有所帮助。
1、C标准(ISO/IEC 9899:1999 standard)规定fflush(stdin)操作是未定义的<参看《ISO/IEC 9899:1999 standard》p270>;。也就是说不一定能实现刷新功能,但有的编译器可能不遵循标准,对fflush(stdin)操作不予警告,并且有时可能产生正确的结果,但最好不要这样使用。
[quote]若我们使用setbuf(stdin, buf)来修改系统提供的缓冲区为我们指定的缓冲区,我猜想这时候可以使用fflush(stdin),我已试验了几例都可以,哪位仁兄可以帮忙在linux下试试,我的系统坏了。
所以这种猜测是错误的,不可仿效。至于说MSDN说可以fflush(stdin),估计是
MS的VC的特性吧,但这样编出的程序也就只能属于VC了。
2、为什么C标准规定fflush(stdin)是未定义的呢?其实,fflush()对其他流的刷新也有可能会失败。以下给出几类fflush()可能失败的情况:
The fflush() function shall fail if:
[EAGAIN]
The O_NONBLOCK flag is set for the file descriptor underlying stream and the thread would be delayed in the write operation.
[EBADF]
The file descriptor underlying stream is not valid.
[EFBIG]
An attempt was made to write a file that exceeds the maximum file size.
[EFBIG]
An attempt was made to write a file that exceeds the process' file size limit.
[EFBIG]
The file is a regular file and an attempt was made to write at or beyond the offset maximum associated with the corresponding stream.
[EINTR]
The fflush() function was interrupted by a signal.
[EIO]
The process is a member of a background process group attempting to write to its controlling terminal, TOSTOP is set, the process is neither ignoring nor blocking SIGTTOU, and the process group of the process is orphaned. This error may also be returned under implementation-defined conditions.
[ENOSPC]
There was no free space remaining on the device containing the file.
[EPIPE]
An attempt is made to write to a pipe or FIFO that is not open for reading by any process. A SIGPIPE signal shall also be sent to the thread.
The fflush() function may fail if:
[ENXIO]
A request was made of a nonexistent device, or the request was outside the capabilities of the device.
3、
关于函数setbuf(stream, buf)和setvbuf(stream, buf, mode, BUFSIZ)
1) setbuf(stream, buf)中,当buf不是空指针时,它应该(shall be)等同于setvbuf(stream, buf, _IOFBF, BUFSIZ);setbuf(stream, buf)中,当buf是空指针时,它应该(shall be)等同于setvbuf(stream, buf, _IONBF, BUFSIZ).
2) setbuf(stream, buf)中buf的大小至少应为BUFSIZ(DEV-C++为512bytes),所以前面讨论的设置buf[10]对于普通PC机是错误的,自己定义缓冲区大小应比标准规定的大(C89规定为256bytes)。
3) 还有一点需要注意:调用setbuf()分配的BUFSIZ个字节的空间不一定表示这些空间都来用作缓冲区(With setbuf(), allocating a buffer of BUFSIZ bytes does not necessarily imply that all of BUFSIZ bytes are used for the buffer area.《http://www.opengroup.org/onlinep ... nctions/setbuf.html》)
4) 像楼主的程序中在main()函数内部调用setbuf(stream, buf),buf声明为一个局部变量是有问题的,因为是操作系统来完成流操作的大部分后台(关闭、打开等)工作。main()函数完成后,buf被释放,操作系统就找不到了流的缓冲区,这样一来就引发了错误。所以自定义缓冲区一定得是全局变量或静态变量。
引用Eric Sosman的话:
You've asked stdin to use a buffer that will cease to exist as soon as main() returns, but when main() returns stdin is still "alive" and hasn't been closed. If any shutting-down operations try to make use of the now- vanished buffer, there's no telling what could happen. (True, this is usually more troublesome for output streams than for input, but you're begging for trouble.) |
|