標準 I/O 庫演進:FORTRAN IV 邏輯單元號 (LUN) → UNIX 文件描述符 (小整數) + 標準流 (stdin/stdout/stderr) + 統一文本流格式 (換行符結尾) → C 標準庫繼承並標準化 (ANSI C89)。
typedef struct _iobuf {
char *_ptr; // 緩衝區當前位置指針
int _cnt; // 緩衝區剩餘字節數
char *_base; // 緩衝區基址
int _flag; // 標誌位 (_IOREAD, _IOWRT, _IORW, _IOBUF, _IOSTRG...)
int _file; // 文件描述符 (底層 handle)
int _charbuf; // 無緩衝時單字符緩衝
int _bufsiz; // 緩衝區大小
char *_tmpfname; // 臨時文件名 (tmpfile 用)
} FILE;
關鍵:FILE* 傳遞的是指針,**不可複製結構體副本使用**,因為內部指針 (_ptr, _base) 指向共享緩衝區。
#define _IOB_ENTRIES 20
FILE _iob[_IOB_ENTRIES] = {
{_bufin, _INTERNAL_BUFSIZ, _bufin, _IOREAD | _IOYOURBUF, 0, 0, _INTERNAL_BUFSIZ, NULL}, // stdin (0)
{NULL, 0, NULL, _IOWRT, 1, 0, 0, NULL}, // stdout (1)
{NULL, 0, NULL, _IOWRT, 2, 0, 0, NULL}, // stderr (2)
// ... 剩餘 17 項初始化為 0
};
#define _NSTREAM_ 512 // 最大並發流數
FILE **__piob; // 指向 FILE* 陣列的指針
// 初始化 (進程啟動時)
__piob = (FILE**)_calloc_crt(_NSTREAM_, sizeof(FILE*));
for (i=0; i<_IOB_ENTRIES; i++) __piob[i] = &_iob[i]; // 掛載靜態流
// 其餘 __piob[20]~__piob[511] 初始為 NULL,按需分配
驗證:fopen 509 個文件 + 3 標準流 = 512 達上限。
FILE * _getstream(void) {
for (i=0; i<_nstream; i++) {
if (__piob[i] == NULL) { // 空槽位
__piob[i] = (FILE*)_malloc_crt(sizeof(_FILEX)); // 分配擴展結構
// 初始化關鍵字段
stream->_flag = stream->_cnt = 0;
stream->_tmpfname = stream->_ptr = stream->_base = NULL;
stream->_file = -1;
return (FILE*)stream;
}
}
// 兼容舊版:掃描 _iob 陣列尋找 _flag==0
return NULL; // 耗盡
}
_getstream() 獲取 FILE*_openfile() 解析模式字串 ("r", "w", "rb"...),設置 _flag (_IOREAD/_IOWRT...),調用底層 open() 獲取文件描述符存入 _fileFILE*深入 _flsbuf (刷新寫緩衝)、_filbuf (填充讀緩衝)、fread/fwrite 塊操作、fseek/ftell 定位實現、臨時文件機制。