浅解C语言的标准输入输出、标准错误
来源:互联网 发布:win10未识别的网络wifi 编辑:程序博客网 时间:2024/06/02 03:09
我们都知道用printf( xxx )和fprintf( stdin, xxx )是一个效果。所以stdin是一个FILE*类型的变量。同样的stdout和stderr也是。
他们的定义在stdio.h(GNU实现)里,其中部分代码如下:
/* Standard streams. */extern struct _IO_FILE *stdin; /* Standard input stream. */extern struct _IO_FILE *stdout; /* Standard output stream. */extern struct _IO_FILE *stderr; /* Standard error output stream. */#ifdef __STDC__/* C89/C99 say they're macros. Make them happy. */#define stdin stdin#define stdout stdout#define stderr stderr#endif
规范要求这几个变量必需是宏,所以后面跟了几个宏,当然这么做是有风险的,例如如下代码:
int main() { setbuf( stdout, NULL ); fprintf( stdout, "hello, " ); stdout = stdout + 1; fprintf( stdout, "world! "); return 0;}编译不会有问题,但是运行时段错误。后来我又看了一下微软的标准库代码,是这样的:
#define stdin (&__iob_func()[0])#define stdout (&__iob_func()[1])#define stderr (&__iob_func()[2])从一个函数返回值中取地址,这时stdout就不是左值了,是禁止被赋值的,编译时就会出错。
在VC6时代,微软似乎也是用了一个静态数组_iob[],直接从这个数组中取值,这和GNU实现方法差不多,都有被改变值的危险。参看:http://blog.csdn.net/wanglei5695312/article/details/5402607
其实FILE是一个结构体_IO_FILE的别名宏,里面包含了文件描述符号,读写指针偏移值等信息,在libio.h中可以找到:
struct _IO_FILE { int _flags; /* High-order word is _IO_MAGIC; rest is flags. */#define _IO_file_flags _flags /* The following pointers correspond to the C++ streambuf protocol. */ /* Note: Tk uses the _IO_read_ptr and _IO_read_end fields directly. */ char* _IO_read_ptr; /* Current read pointer */ char* _IO_read_end; /* End of get area. */ char* _IO_read_base; /* Start of putback+get area. */ char* _IO_write_base; /* Start of put area. */ char* _IO_write_ptr; /* Current put pointer. */ char* _IO_write_end; /* End of put area. */ char* _IO_buf_base; /* Start of reserve area. */ char* _IO_buf_end; /* End of reserve area. */ /* The following fields are used to support backing up and undo. */ char *_IO_save_base; /* Pointer to start of non-current get area. */ char *_IO_backup_base; /* Pointer to first valid character of backup area */ char *_IO_save_end; /* Pointer to end of non-current get area. */ struct _IO_marker *_markers; struct _IO_FILE *_chain; int _fileno;#if 0 int _blksize;#else int _flags2;#endif _IO_off_t _old_offset; /* This used to be _offset but it's too small. */#define __HAVE_COLUMN /* temporary */ /* 1+column number of pbase(); 0 is unknown. */ unsigned short _cur_column; signed char _vtable_offset; char _shortbuf[1]; /* char* _save_gptr; char* _save_egptr; */ _IO_lock_t *_lock;#ifdef _IO_USE_OLD_IO_FILE};
我们知道,linux操作系统都是通过文件描述符号(一个整数值)来确定对文件的api调用的,而windows是通过维护一个[文件描述符,句柄]的map,直接通过文件描述符获取内核句柄的,具体参看:http://www.cnblogs.com/fullsail/archive/2012/10/21/2732873.html
这个值就是上面结构体中的_fileno,那么stdin、stdout、stderr对应的文件描述符号分别是多少呢?我们来看unistd.h中的一段代码:
/* Standard file descriptors. */#define STDIN_FILENO 0 /* Standard input. */#define STDOUT_FILENO 1 /* Standard output. */#define STDERR_FILENO 2 /* Standard error output. */
另外,提一下stdout和stderr的输出模式的区别,默认情况下,stdout上绑定了一个缓冲区,会在遇到换行符‘\n’或缓冲区满时输出,而stderr是立即输出。
一个intel面试题是写出下列代码输出:
int main() { fprintf( stdout, "hello, " ); fprintf( stderr, "world! "); return 0;}
输出应该是“world!hello, ”,当然可以通过setbuf/setvbuf函数来改变一个FILE*对应的缓冲区。
- 浅解C语言的标准输入输出、标准错误
- C语言标准输入输出
- C语言 标准输入输出
- c 语言的标准输入输出,scanf,printf
- C语言标准输入输出函数
- C语言标准输入输出函数
- C语言标准输入输出体会
- 输入输出原理与C语言标准输入输出函数
- C语言的标准
- C语言的标准
- C语言的标准
- C语言的标准
- C语言的标准
- 标准输入输出与错误的缓冲
- c 标准输入输出
- C标准输入输出
- Linux-C标准输入输出
- 标准C-----文件的输入输出函数
- ArcPy - 入门学习
- fusioncharts错误提示的汉化,基本故障排除,下载功能配置
- [HTML]显示/隐藏DIV的技巧(visibility与display的差别)
- WINCC6.2 VB脚本如何对变量进行位操作?
- OTL编程技术
- 浅解C语言的标准输入输出、标准错误
- 龙芯一号cpu网络计算机硬件设计与实现
- zendframework 上传图片判断 .
- HDU2063过山车(二分匹配)
- freeswitch的拨号规则配置
- 构造函数、析构函数是否要声明为虚函数的问题
- apache http server 安装的时候选择 “for current user”,如何正常启动?(jung)
- MSP430编程器仿真器JTAG、SBW、BSL接口的区别
- QTP11.5(HP UFT 11.5)下载地址