printf的返回值大部分情況下是沒有必要關注的, 因為關注了也不會帶來好處, 每次都關注的高成本也許會讓你放棄.
然而,它的返回值卻值得研究.
q: printf("貓")返回值是多少?
a: printf_ret.c
#include #include #include #ifndef pd
#define pd(str) printf(#str ":%d\n", (str))
#endif
int main(int argc, char *ar**)
執行結果:
123ret:3
貓ret:3
源**預設編碼是utf-8, "貓"的utf-8格式是3位元組, 所以返回3.
q: 為什麼printf返回的是位元組數, 不是字元數?
a: 從c語言的角度, 它不應該和所謂的"字元"打交道, 因為"字元"可能有n種編碼格式,對應的位元組數都可能不一樣, libc也不應該
為不同編碼格式決定返回值, 否則會讓libc變成乙個大雜燴. 如果真的要這個返回值, 也應該為此單獨寫乙個api.
q: "貓"是如何被儲存的?
a: lldb除錯讀到的資料如下:
可以看到, "貓"被儲存為e7 8c ab (lsb --> msb), 查詢utf-8編碼表可以對上.
q: 我們知道了printf返回值的原理, 我們是不是可以動態修改資料?
a:是的, 修改資料為"ab", 返回值變成了2, 結果如下:
q: 在編譯的靜態二進位制檔案中如何找到"貓"的儲存位置?
q: 如何在libc看到printf返回值是如何計數的?
a: printf最終會call到vfprintf, return計數預設按位元組計算(如下的ch和fmt分別是char和char *型別, 資料預設為1位元組).
q: 如何構造出printf的返回值和預期不一致的情形?
a: 利用printf不支援的格式串讓內部不能正常計數輸出的位元組數.
#include #include #include #ifndef pd
#define pd(str) printf(#str ":%d\n", (str))
#endif
int main(int argc, char *ar**)
結果:
ret:0
所以, 這個時候可以看到, 返回值有的時候還是有作用的, 為了檢測輸出的資料而做防範, 通過它確保輸出是否有異常.
q: 除了上面為了檢測異常輸出的情況, 返回值真的沒有用處了嗎?
a: 使用者空間透過sysfs等機制得到kernel資訊時,不可避免地需要用"printf系列/scanf系列"的返回值,而這個時候,正是利用printf系列返回值最佳的時機: 因為無法保證內部組裝的字串都是常量, 一旦涉及到格式, 依賴程式設計師"直接"統計將是無法保證的任務.
如下是linux cpufreq driver顯示cpus資訊利用scnprintf/sprintf計數統計值.
q: c語言有沒有內部計數printf的資訊?
a: %n 可以記錄當前已經輸出的位元組數, 且不額外占用統計值.
#include #include #include #ifndef pd
#define pd(str) printf(#str ":%d\n", (str))
#endif
#ifndef pd2
#define pd2(str1, str2) \
printf(#str1 ":%d, " #str2 ":%d\n", (str1), (str2))
#endif
int main(int argc, char *ar**)
結果:
環境: macos 10.14.5
scanf 返回值 你想知道的C語言 2 1
q scanf的返回值和printf返回值一樣嗎?a scanf的返回值和printf返回值不一樣,scanf對於輸入多少字元並不敏感,大多數情況下毫無意義.但它對輸入的變數個數很感興趣.參考 printf 返回值 你想知道的c語言 1.1 these functions scanf fscanf....
printf的返回值
初學c語言時用的最多的函式就是printf函式,而printf函式的返回值是被大多數人忽略的,以至於很多應聘者在碰到關於printf返回值的程式設計時一頭霧水。確實很少人會注意到這個,接下來就談一談printf返回值的問題。先看看下面的程式 include int main 這個程式就是用了幾個pr...
printf函式的返回值
先看下面一段程式 文末會給大家推薦幾本好書,希望能夠需要的朋友一點幫助!include int main printf函式裡面又嵌入了printf函式,你認為此段程式會列印出什麼?程式的實際執行結果是 對於這個執行結果,你怎麼看?我們來一步步分解printf函式,看看為啥會輸出這個結果。程式中的pr...