\r 和 \n 的區別
- \r 表示回車 (回車表示換到當前行的最開始)
- \n 表示換行(換行只是換到下一行)
- 注意:但是在實際使用時,\n 就直接表示了 \r\n 回車換行。
緩衝區的概念
-
行緩衝:常見的是對顯示器進行刷新數據時
- 即必須緩衝區中一行填滿了或者遇到 \n 才會輸出到顯示器
-
全緩衝:對文件進行寫入時採用全緩衝
- 即將整個緩衝區填滿才會刷新到磁盤中。
- 無緩衝:即刷新數據時沒有緩衝區。
行緩衝示例一:
-
下列代碼執行後的結果是:停止5秒後才顯示 hello world
- printf 這行代碼是先執行的
- 但是 printf 中沒有 \n ,並且緩衝區中的一行並沒有填滿,所以沒有輸出到顯示器
- 所以繼續執行下面的 sleep 代碼
- 在程序結束後會刷新緩衝區,將緩衝區的內容輸出到顯示器,所以最後仍然會顯示。
void test()
{
printf("hello world"); //加入 \n 後就會立即輸出到顯示器了。
sleep(5);
}
行緩衝示例二
- 下列代碼顯示結果為:倒計時,並且下一次的數字會覆蓋上一次的數字。
- 因為 \r 只是回車,並未換行,所以依然會在之前那一行繼續輸出
- 並且回車後,會回到這一行的起始位置,所以覆蓋了上一次的值。
#include <unistd.h>
void test()
{
int i = 10;
while(i)
{
printf("%2d\r",i); //%2d 表示顯示兩個字符
fflush(stdout); //fflush是一個庫函數,用來立即刷新緩衝區輸出到顯示器中
sleep(1);
i--;
}
}
全緩衝與無緩衝示例一
#include <stdio.h>
#include <unistd.h>
#include <string.h>
int main()
{
//C語言函數
printf("hello printf\n");
fprintf(stdout,"hello fprintf\n");
//系統函數
const char * msg = "hello write\n";
write(1,msg,strlen(msg));
fork();
return 0;
}
- 正常輸出到顯示器中時,是正常顯示三行
- 但是重定向輸出到文件中時,會多打印2行
- 當往顯示器中打印時,系統採用的是行緩衝,即運行到 printf 等函數後,立馬將數據刷新到顯示器。
- 但是當重定向打印到文件時,緩衝方式發生變化,變成全緩衝,全緩衝會等到程序結束時,一次性將緩衝區內容打印到文件中
- 程序最後創建了子進程,子進程會繼承父進程的緩衝區(子進程的緩衝區和父進程緩衝區內容相同,但是不是一個緩衝區,進程的獨立性,發生寫實拷貝)
- 所以父進程刷新一次緩衝區後,子進程也會刷新緩衝區,所以會打印兩次 C 函數的內容。
- 因為系統函數(系統接口)沒有緩衝區,所以 write函數只打印一次,並且是第一個被打印。
緩衝區位置
- 緩衝區是由 C 語言本身自帶的,所有的 C 函數接口都有緩衝區,而系統接口沒有緩衝區。
- 緩衝區是維護在文件結構體 files_struct 中,files_struct 提供文件描述符和用户緩衝區。