我正在经历K&R
。我对以下stdio.h
的摘录有点困惑。
typedef struct _iobuf {
int cnt; /* characters left */
char *ptr; /* next character position */
char *base; /* location of buffer */
int flag; /* mode of file access */
int fd; /* file descriptor */
} FILE;
extern FILE _iob[OPEN_MAX];
#define stdin (&_iob[0])
#define stdout (&_iob[1])
#define stderr (&_iob[2])
这里,FILE
被定义为结构,并且stdin
、stdout
、stderr
是类型为FILE
的阵列的前三个成员。那么(&_iob[0])
、(&_iob[1])
或(&_iob[2])
对standard input device
和standard output device
的赋值写在哪里?
这里,_iob[OPEN_MAX];
被声明为extern
变量为extern FILE _iob[OPEN_MAX];
。这意味着,_iob[OPEN_MAX];
由一些其他代码填充,并且有一个初始代码分配(&_iob[0]), (&_iob[1]) or (&_iob[2]) to stdin, stdout and stderr
此赋值可能是由main()
之前运行的一些初始化代码执行的。
除其他外,这段代码应该将这些数组条目链接到它们各自的文件描述符,这些描述符已经由操作系统的加载程序打开。
我知道这个问题是在2013年提出的。也许,这本书的作者已经知道答案了。但是,由于这个话题由于缺少一个经过检查的正确答案而悬而未决,我将把我的观点留在这里。
我认为,即使重新实现了一些io函数,系统(Unix)与文件描述符之间的设备stdin、stdout和stderr之间的关联仍然保持不变。
所以,我认为这本书的这篇文章就是这个问题的答案:
FILE _iob[OPEN_MAX] = { /* stdin, stdout, stderr : */
{ 0, (char *) 0, (char *) 0, _READ, 0 },
{ 0, (char *) 0, (char *) 0, _WRITE, 1 },
{ 0, (char *) 0, (char *) 0, _WRITE | _UNBUF, 2 }};
每次发生读或写函数时,这些文件描述符都会传递给它们。而且,由于这些功能(读和写)没有重新实现,系统知道在哪里可以连接这些文件描述符。
您可以尝试一种方法。在windows下,我使用llvm ojbdump search_iob相关符号。
llvm-objdmp -t libucrt.lib > symbol.txt
在symbol.txt文件中找到关键字"_iob",我找到了符号__acrt_ob_func,然后构造块代码进行验证。
extern FILE* __acrt_iob_func(unsigned);
#define stdin (__acrt_iob_func(0))
#define stdout (__acrt_iob_func(1))
#define stderr (__acrt_iob_func(2))
您可以使用其他工具来转储C库的符号,然后搜索您需要的符号。