在 Windows 下鍵入 Enter 鍵,是在鍵盤緩衝區中存入 還是 兩個?
首先,題主要說明這個鍵盤緩衝區是指什麼呢?
以一個USB鍵盤為例,從USB的請求開始到最終窗口收到消息,中間有好幾層緩衝區,每層都不太一樣。
USB驅動一層有緩衝區,這裡保存的都是掃描碼,不區分換行符。
如果是使用directX的directIO進行按鍵輸入管理,那麼這一層就可以直接把按鍵信息拿走,有些遊戲(比如LOL)就是這麼做的。
所有鍵盤消息最終都發送到Windows鍵盤的一個統一驅動里叫kbdclass.sys,這個驅動負責統一翻譯、處理、管理所有鍵盤以及消息。這一層,應該還是掃描碼。
之後,這個消息就通過內核到用戶態了。
在用戶態里,進程csrss.exe有一個線程win32k!RawInputThread負責處理按鍵,廣播按鍵消息。此時掃描碼變成按鍵(包括區域符號轉化)是"
"
csrss.exe調用DispatchMessage等函數分發消息給各個窗口、線程等。
各個窗口收到按鍵消息,此時仍然是"
".
部分窗口會根據按鍵消息做文本轉換,轉換完以後,看到的才是"
".
對於命令行的C語言,由Windows的POSIX子系統或者其它模塊負責接收按鍵消息,在LibC一層通過stdio/stdlib這些庫轉化成"
".
所以,如果你操作的內容位於文本框(以及其它Windows文本環境)、命令行的LibC環境(包括但不限於stdio、iostream庫),那麼收到的應該是"
",其它情況,比如Windows按鍵消息等,多數收到的都是"
"
當然,如果在MS開發環境下,真正到具體使用中的時候,還是分很多情況的:比如字元串"
"在以非binary方式寫入文件的時候,是"
",在以binary寫入文件的時候,是"
",getchar返回的是"
",但不是絕對的,要根據你輸入的數據流決定,有時候,如果輸入的數據流是文件,而非鍵盤控制台,那麼文件里的"
"到了你的函數里,就變成了"
"。所以,一個字元流可能保存在內存里的時候是"
",但你getchar得到的是"
",寫到文件里卻是"
"。
所以,只能說,用實踐去嘗試,尤其做開發,甚至會出現不同的開發環境里返回值不同的情況。如果非要做嚴格檢查,建議同時檢查"
", "
", "
", "
"
另附上Windows按鍵消息的處理流程:
一個按鍵的消息產生流程如下:
1)硬體中斷/硬體埠數據
//WinIO能模擬,或者修改IDT是在這一層2)鍵盤Port驅動(USB or PS/2)//Filter驅動在此//DirectIO在此//KeyboardClassServiceCallback也在這一層被調用3)kbdclass驅動//處理鍵盤布局和鍵盤語言,部分高端的病毒也工作在這裡4)Windows內核邊界(zwCreate/zwReadFile)
----------------------(系統調用)----------------------5)Windows內核邊界(zwCreate/zwReadFile)6)csrss.exe的win32k!RawInputThread讀取,完成scancode和vk的轉換//SetWindowHook工作在這裡(全局)//kbd_event工作在這裡7)csrss.exe調用DispatchMessage等函數分發消息//SetWindowHook工作在這裡(進程)//PostMessage和SendMessage在這裡8)各個進程處理消息9)子系統、LibC、文本框、輸入法轉換按鍵到最終字元(符號)
另外,評論里有人問為什麼Windows設計的這麼複雜,這是一個歷史問題,Windows不是一次設計完的,歷經30多年的變遷積累了很多東西,其中一個特點就是vk(虛擬按鍵?),這是一個DWORD(32bit)類型的數據,用來描述各種鍵盤狀態,因為一個面向事件的系統就必須要能處理各種按鍵的彈起、落下、組合鍵,而如果考慮到各種地區的鍵盤布局(比如歐洲地區的鍵盤布局),這種鍵位組合數量龐大,所以才用DWORD表示。而後來軟體又希望提供directIO以及各種hook請求,就慢慢演變成如今這種這麼複雜的東西。WM_CHAR 消息只有 0x0D。
很難說這個「鍵盤緩衝區」是什麼?有人用這個概念來解釋為什麼有些庫函數調用不立即響應鍵盤輸入。道理上貌似說得通,但實際情況究竟如何,其實是一筆糊塗賬。因為這涉及到操作系統的一些複雜的機制。我不太清楚題主這個問題的動機,了解這個問題答案的目的是什麼。但在我看來這個問題與「鍵盤緩衝區」沒什麼關係。實際上與Windows下流的性質相關。Windows下文本流中
表現為 xd xa,無論是輸入還是輸出。由於在C語言中將標準輸入設備視為文本流,所以回車應該視為 xd xa。但對於程序來說這沒什麼意義,因為即使標準輸入流中是 xd xa,但接受之後還是按照binary存儲(機器內部不存在文本),即只需要一個char來接受,你得到的也只是一個
。而在其他的系統下,可能根本就沒有文本流這個概念,這時你得到也是一個
。如此,對你來說又有什麼分別呢?這就是我認為這個問題沒有實際意義的原因。唯一的分別將會體現在你將標準輸入流這個文本流視為二進位流的情況下,你會從標準輸入流中讀出
。我想不出什麼樣的程序會有這樣的需求。
Windows是"
",Linux是"
",MacOS是"
".
如果從鍵盤事件來說,應該只會有一個
可實測為 「
」。1:用記事本新建一個txt文檔,敲回車,再輸入一個字元"a";保存;2:用ultraEdit打開這個txt文檔,切換到十六進位顯示,結果顯示為 0D 0A 61;3:由此證明windows下默認敲回車是
.
從來都記不清,就notepad++打開,show all symbols
推薦閱讀:
※為什麼用C/C++編寫的程序只能用鍵盤輸入,而且輸出結果也只能在一個黑屏上顯示是一些字元?
※現在C++11/14有很多公司在用嗎?
※一段很有意思的代碼,你能說出為什麼結果是這樣嗎?
※既然c++的非virtual的函數可以重定義,virtual函數相比非virtual的有什麼優勢?
※用MFC做的貪吃蛇遊戲,求大神。?