作者loveflames (咕啾咕啾魔法陣)
看板C_and_CPP
標題[心得] cout、cerr、clog的輸出順序
時間Sun Jun 6 08:44:50 2010
以下是標準的做法
stderr:預設沒有分配buffer
stdout:預設有分配buffer
cout:用stdout的buffer
clog:用stderr的buffer
cerr:用stderr的buffer,強制清空buffer
因為每個compiler的預設值可能不同,可能有人因此搞混,所以整理一下重點,
首先看cout.flags()、clog.flags()、cerr.flags()的值,大小為15個bit,
第二高的那個bit(即ios::unitbuf)若為1,代表會強制清空buffer,反之則否,
一般來說只有cerr會設這個bit,但不排除有全部都設的compiler存在,
接下來則要看該stream的buffer,像stderr預設為沒有,(clog跟cerr都是用stderr)
所以就比stdout早輸出,如果有compiler會偷偷跑fflush()的話,那就沒差了....
因為有些不按照標準,沒分配buffer給stdout
=======================================================================================
#include<iostream>
char buf[10];
using namespace std;
int main(){
setbuf(stderr,0);//為了避免compiler偷偷分配buffer給stderr
cout<<"123";
clog<<"456";
cerr<<"789";
}
這裡只有cerr有設ios::unitbuf,輸出順序卻是456123789,而不是456789123,
原因是cerr.tie()=&cout,這代表當cerr要清空時,會先清空前面cout的buffer
=======================================================================================
#include<iostream>
char buf[10];
using namespace std;
int main(){
setbuf(stderr,0);
cout<<"123";
cerr<<"456";
clog<<"789";
}
順序換一下,就變成123456789
=======================================================================================
#include<iostream>
char buf[10];
using namespace std;
int main(){
setbuf(stderr,buf);
cout<<"123";
clog<<"456";
cerr<<"789";
}
那麼把0改成buf會怎樣? 輸出會變成123456789,因為此時clog的buffer大小已經不為0了
=======================================================================================
#include<iostream> #include<iostream>
char buf[10]; char buf[10];
using namespace std; using namespace std;
int main(){ int main(){
cerr.tie(0); cerr.tie(0);
setbuf(stderr,buf); setbuf(stderr,buf);
cout<<"123"; cout<<"123";
clog<<"456"; cerr<<"456";
cerr<<"789"; clog<<"789";
} }
接下來看clog跟cerr對調會如何,首先將cerr跟cout的關聯去掉,
左邊的輸出是456789123,右邊的輸出是456123789,
因為左邊的cerr強制清空stderr的buffer,導致clog比cout更早輸出,
而右邊的clog就只能乖乖等結束的時候執行fflush()
=======================================================================================
#include<iostream>
char buf[10];
using namespace std;
int main(){
setbuf(stderr,buf);
cout.setf(ios::unitbuf);
cerr.unsetf(ios::unitbuf);
clog.unsetf(ios::unitbuf);
cerr<<"123";
clog<<"456";
cout<<"789";
}
讓cout反其道而行的方法,輸出為789123456,setbuf那行若改回0,則為123456789
=======================================================================================
#include<iostream> #include<iostream>
char buf[10]; char buf[10];
using namespace std; using namespace std;
int main(){ int main(){
setbuf(stderr,buf); setbuf(stderr,0);
fprintf(stdout,"123"); fprintf(stdout,"123");
fprintf(stderr,"456"); fprintf(stderr,"456");
} }
最後附上stderr跟stdout的範例 ,左邊是123456,右邊是456123
=======================================================================================
另外用setbuf()時,buffer千萬不能是local,
因為最後執行fflush()時,main()已結束了
參考的spec:
http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1124.pdf
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2010/n3035.pdf
--
C++ hello world標準寫法
http://nopaste.csie.org/fee97
--
※ 發信站: 批踢踢實業坊(ptt.cc)
◆ From: 140.134.226.149
推 diabloevagto:寫的不錯喔!不過建議分配三種輸出的時候,用比較好 06/06 14:52
→ diabloevagto:分辨的,譬如用AAAaaa111這樣會比較好分辨。 06/06 14:53
※ 編輯: loveflames 來自: 140.134.226.149 (06/06 15:23)
推 nowar100:推您的熱心 06/06 16:16
突然想到有些東西忘了講,再補充一下
=======================================================================================
#include<iostream>
char buf[10];
using namespace std;
int main(){
setbuf(stderr,buf);
cerr<<"123";
clog<<"456";
cout<<"789";
}
輸出是123789456,因為執行exit()後,先flush stdout,再flush stderr
(標準好像沒有規定順序,應該跟下面的例子類似)
=======================================================================================
#include<iostream>
char buf[10];
using namespace std;
int main(){
setbuf(stderr,buf);
clog<<"123";
cout<<"456\n";
}
因為stdout是line buffered,所以先輸出456,兩個順序對調的話,則是123456
(stdout是line buffered似乎不是標準,而是implementation-defined,標準只說
要有buffer,不過好像多數compiler預設都是line buffered,還沒看過不是的)
=======================================================================================
#include<iostream>
char buf[10];
using namespace std;
int main(){
setbuf(stderr,buf);
cout<<"123";
clog<<"456\n";
}
endl跟\n的不同是,前者有flush的作用,後者只是單純換行,
這個程式的輸出為123456,如果把\n改成endl,則先輸出456
=======================================================================================
※ 編輯: loveflames 來自: 140.134.226.149 (06/06 19:52)