C 标准输入和标准输出的标准输入、标准输出和标准输出的实际分配

C 标准输入和标准输出的标准输入、标准输出和标准输出的实际分配,c,stdout,stdin,kernighan-and-ritchie,C,Stdout,Stdin,Kernighan And Ritchie,我正在经历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 */ }

我正在经历
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])

这里,
文件
被定义为一种结构,
stdin
stdout
stderr
文件
类型数组的前三个成员。那么
(&&u iob[0])
(&&u iob[1])
(&&u iob[2])
标准输入设备和
标准输出设备的赋值写在哪里呢?

这里,
\u iob[OPEN\MAX]声明为
extern
变量为
extern FILE\u iob[OPEN\u MAX]。这意味着,
\u iob[OPEN\u MAX]
由一些其他代码填充,并且有一个初始代码将
(&_iob[0])、(&_iob[1])或(&_iob[2])分配给stdin、stdout和stderr

此分配可能由在
main()
之前运行的一些初始化代码执行


除其他外,该代码应该将这些数组项链接到它们各自的文件描述符,这些文件描述符已经由操作系统的加载程序打开。

您可以尝试一种方法。在windows下,我使用llvm ojbdump搜索相关符号

llvm-objdmp -t libucrt.lib > symbol.txt
在symbol.txt文件中找到关键字“\u iob”,我找到了symbol\uu acrt\u iob\u 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库的符号,然后搜索所需的符号。

我知道这个问题是在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 }};

每次读或写函数发生时,这些文件描述符都会传递给它们。而且,由于这些功能(读和写)没有重新实现,系统知道在哪里连接这些文件描述符。

那么你是说即使
文件
以前也在其他地方声明过吗?@noufal你听起来很惊讶。是的,通常必须在某处声明才能使用。从
fopen()
调用中得到的是一个
文件*
,它指向库通过某种方式分配的
文件
,并填充了相关信息。但是这个声明必须由库来完成,而不是应用程序程序员的事情。