priintf为什么能写到屏幕上文字呢?

用了这么多年的printf(),都不知道priintf到底做了什么,悲哀啊!

刚刚看看看VC的源码,原来printf使用_write写了字符串到文件句柄为1的文件中,这个句柄就是屏幕的句柄

printf函数:

int __cdecl printf (
        const char *format,
        ...
        )

{

...  // 这里是一些处理不定参数的操作,就是把第一个参数的指针依次加一,就得到第二个、第三个、...参数,就不介绍了,

    _ftbuf(buffing, stdout);

...

}

而stdout的定义是:

#define stdout (&__iob_func()[1])

函数__iob_func()又在是_file.c中实现的:

/*
 * FILE descriptors; preset for stdin/out/err (note that the __tmpnum field
 * is not initialized)
 */
FILE _iob[_IOB_ENTRIES] = {
        /* _ptr, _cnt, _base,  _flag, _file, _charbuf, _bufsiz */

        /* stdin (_iob[0]) */

        { _bufin, 0, _bufin, _IOREAD | _IOYOURBUF, 0, 0, _INTERNAL_BUFSIZ },

        /* stdout (_iob[1]) */

        { NULL, 0, NULL, _IOWRT, 1, 0, 0 },

        /* stderr (_iob[3]) */

        { NULL, 0, NULL, _IOWRT, 2, 0, 0 },

};


/* These functions are for enabling STATIC_CPPLIB functionality */
_CRTIMP FILE * __cdecl __iob_func(void)
{
    return _iob;
}

这里首先定义了一个有文件结构的数组的数组

__cdecl __iob_func返回了第一个,在#define stdout (&__iob_func()[1]) 有加了1,再取地址 就是返回了第二个文件的指针

这里没有定义文件名FILE结构(第8个指针是文件名)有文件名,因为不用文件名,输出到屏幕了还要什么文件名啊

 

接下来看看函数_ftbuf:

/***
*int _flush(stream) - flush the buffer on a single stream
*
*Purpose:
*       If file open for writing and buffered, flush the buffer.  If
*       problems flushing the buffer, set the stream flag to error.
*       Multi-thread version assumes stream lock is held by caller.
*
*Entry:
*       FILE* stream - stream to flush
*
*Exit:
*       Returns 0 if flushed successfully, or if no buffer to flush.,
*       Returns EOF and sets file error flag if fails.
*       File struct entries affected: _ptr, _cnt, _flag.
*
*Exceptions:
*
*******************************************************************************/

int __cdecl _flush (
        FILE *str
        )
{
        REG1 FILE *stream;
        REG2 int rc = 0; /* assume good return */
        REG3 int nchar;

        /* Init pointer to stream */
        stream = str;


        if ((stream->_flag & (_IOREAD | _IOWRT)) == _IOWRT && bigbuf(stream)
                && (nchar = (int)(stream->_ptr - stream->_base)) > 0)
        {
                if ( _write(_fileno(stream), stream->_base, nchar) == nchar ) {  // 这里写入了字符串
                        /* if this is a read/write file, clear _IOWRT so that
                         * next operation can be a read
                         */
                        if ( _IORW & stream->_flag )
                                stream->_flag &= ~_IOWRT;
                }
                else {
                        stream->_flag |= _IOERR;
                        rc = EOF;
                }
        }

        stream->_ptr = stream->_base;
        stream->_cnt = 0;

        return(rc);
}

大家一定注意到了函数_fileno,再看看_fileno:

int __cdecl _fileno (
        FILE *stream
        )
{
        _VALIDATE_RETURN((stream != NULL), EINVAL, -1);
        return( stream->_file );
}

从_iob的定义中可以看出就是返回了一个1

那么,看了上面的分析我们就可以使用如下方式写到屏幕上字符了

char mc[] = "This is MyString/n";

_write(1,mc,strlen(mc));

快去试试吧!

提醒:

1.屏幕输出的文件句柄为1,不知道能不能跨平台,我没有看过其他的系统系的屏幕输出怎么写的

2.prinf中使用了_lock_str2(1, stdout);和_unlock_str2(1, stdout);来给屏幕文件加锁和解锁

   这是为了如果多线程中同时有几个线程要输出到屏幕,可能会乱了。

 

你可能感兴趣的:(多线程,Stream,File,null,buffer,跨平台)