UNIX「一切皆文件」。Shell 啟動程序時預打開 3 個描述符:
0 - stdin(標準輸入)1 - stdout(標準輸出)2 - stderr(標準錯誤)重定向 prog < in > out 由 Shell 修改描述符 0/1 指向,程序無感知。
ssize_t read(int fd, void *buf, size_t n);
ssize_t write(int fd, const void *buf, size_t n);
read 返回 0 表示 EOF,-1 表示錯誤。int getchar(void) {
char c;
return (read(0, &c, 1) == 1) ? (unsigned char)c : EOF;
}
int getchar(void) {
static char buf[BUFSIZ];
static char *bufp = buf;
static int n = 0;
if (n == 0) {
n = read(0, buf, sizeof buf);
bufp = buf;
}
return (n-- > 0) ? (unsigned char)*bufp++ : EOF;
}
| 函數 | 原型 | 說明 |
|---|---|---|
| open | int open(const char *path, int flags, mode_t mode) | flags: O_RDONLY/O_WRONLY/O_RDWR/O_CREAT/O_TRUNC/O_APPEND |
| creat | int creat(const char *path, mode_t mode) | 等價 open(path, O_WRONLY|O_CREAT|O_TRUNC, mode) |
| close | int close(int fd) | 釋放描述符,不刷新緩衝(無緩衝) |
| unlink | int unlink(const char *path) | 刪除目錄項,引用計數歸零時真正刪除文件 |
權限 mode:八進制如 0666(rw-rw-rw-),受 umask 影響。
off_t lseek(int fd, off_t offset, int whence);
// whence: SEEK_SET(0) 開頭, SEEK_CUR(1) 當前, SEEK_END(2) 結尾
// 返回新偏移量,-1 表示錯誤
應用:lseek(fd, 0, SEEK_END) 定位尾部實現追加寫入。
FILE 結構體(簡化版):
typedef struct _iobuf {
int cnt; // 剩餘字符數
char *ptr; // 下一字符指針
char *base; // 緩衝區基址
int flag; // 標誌位
int fd; // 文件描述符
} FILE;
標誌位(位掩碼):_READ(01) _WRITE(02) _UNBUF(04) _EOF(010) _ERR(020)。
全局表:FILE _iob[OPEN_MAX],預置 stdin/stdout/stderr。
getc 宏:
#define getc(p) (--(p)->cnt >= 0 ? (unsigned char)*(p)->ptr++ : _fillbuf(p))
_fillbuf 填充緩衝區:
int _fillbuf(FILE *fp) {
int bufsize = (fp->flag & _UNBUF) ? 1 : BUFSIZ;
if ((fp->flag & (_READ | _EOF | _ERR)) != _READ) return EOF;
if (fp->base == NULL) fp->base = malloc(bufsize);
fp->ptr = fp->base;
fp->cnt = read(fp->fd, fp->ptr, bufsize);
if (--fp->cnt < 0) { /* 設置 EOF/ERR */ return EOF; }
return (unsigned char)*fp->ptr++;
}
fopen 核心邏輯:解析模式 → 在 _iob 找空槽 → open/creat 獲取 fd → 填充 FILE 結構 → 返回指針。
short)節省內存/提速。int x = 0;)比賦值快。c += 5 僅求值一次,c = c + 5 求值兩次。&& 將最可能為假的條件左置;|| 將最可能為真的左置(短路求值)。EOF 而非 -1(ANSI 只保證負數)。long(至少 32 位)。int maximum(int, int, int); // 參數名可省略
作用:編譯期檢查參數個數/類型/順序,自動進行參數類型轉換(如傳 int 給 double 參數)。