按照慣例,UNIX系統shell使用文件描述符0與進程的標準輸入(一般是鍵盤)相關聯,文件描述符1與標準輸出(一般是顯示器)相關聯,文件描述符2與標準出錯輸出(一般是顯示器)相關聯。
在依從POSIX的應用程序中,幻數0、1、2應當替換成符號常量STDIN_FILENO、STDOUT_FILENO和STDERR_FILENO。這些常量都定義在頭文件<unistd.h>中。
一般在教材中不會明確區分,但是我們應注意到標準輸入有兩層含義:一是指STDIN_FILENO(慣例指定的標準輸入設備描述符);另一層含義則是指標準輸入設備(如鍵盤)。同樣,標準輸出也有兩層含義:一是指STDOUT_FILENO(慣例指定的標準輸出設備描述符);另一層含義則是指標準輸出設備(如顯示器)。
scanf函數從標準輸入讀取內容,我們通常會認為是從鍵盤讀取的。PRintf函數把內容輸出到標準輸出,我們通常認為是輸出到顯示器上。這并沒有問題,但前提是“在通常情況下”。
精確地說,scanf函數是從文件描述符STDIN_FILENO(0)所關聯的文件中讀取,而prinf函數則是輸出到文件描述符STDOUT_FILENO(1)所關聯的文件中。
如果STDIN_FILENO關聯的文件不是鍵盤,那么scanf就不會從鍵盤讀取內容,同理,如果STDOUT_FILENO關聯的文件不是顯示器,那么printf也不會將內容輸出到顯示器。
舉例說明(不深究此程序片段意義如何,只為說明上面的敘述而用):
...int fd[2];int pid;pipe(fd);if((pid = fork()) < 0){ perror("fork"); exit(1);}else if(pid == 0) /* 子進程 */{ close(fd[0]); dup2(fd[1], STDOUT_FILENO); ... }else /* 父進程 */{ close(fd[1]); dup2(fd[0], STDIN_FILENO); ...}子進程中,如果在dup2(fd[1], STDOUT_FILENO); 語句后調用printf函數,那么內容并不會輸出到顯示器,而是寫入了管道中。
父進程中,如果在dup2(fd[0], STDIN_FILENO); 語句后調用scanf函數,那么不會從鍵盤讀取內容,而是從管道中讀取。
清楚地了解標準輸入和標準輸出在特定上下文中的確切含義,有時可以避免不必要的困擾。
新聞熱點
疑難解答