一 遇到%n
昨天在寫scanf 的輸入異常處理時遇到了乙個從未見過的格式說明符:%n
sscanf(str, "%d
%n", &v, &c)
從執行結果來看,c的值是str的長度。
二 stack overflow 上關於%n 的qa
於是我在stack overflow上找到了關於這個格式說明符的qa。
what is the use of the %n format specifier in c?
第乙個回答是:
nothing printed. the argument must be a pointer to a signed int, where the number of characters written so far is stored.意思是,不會列印任何東西。 這個引數必須是乙個有符號整數的指標,它儲存它出現之前列印的所有字元數。
並給了乙個例子:
#include
int main()
結果是:
blah blah
val =5
第二個答案給了另乙個例子:
int n;
printf("%s: %nfoo\n", "hello", &n);
printf("%*sbar\n", n, "");
結果是:
hello: foo
bar
三 我的執行異常和除錯情況我決定手動執行一下。
我的程式如下:
#include
int main(void)
我先用mingw的gcc進行編譯執行:
gcc -g %n.c -o %n
結果執行時,一直在列印空格,控制台旁邊的滑塊迅速向下滑行,過了好一會才有字元出現。
我試著用gdb進行除錯:
7 printf("blah %n blah\n", &val);
(gdb) p val
$1 = 4194432
(gdb) n
warning: invalid parameter passed to c runtime function.
blah 8 printf("val = %d\n", val);
(gdb) p val
$2 = 4194432
發現宣告變數時和執行printf("blah %n blah\n", &val)
後,val的值並沒有發生改變,而且丟擲了乙個warning:invalid parameter passed to c runtime function.對於test 2也是同樣的情況。
接著我試著用developer command prompt for vs 2017對該程式進行編譯執行:
cl %n.c
用於 x86 的 microsoft (r) c/c++ 優化編譯器 19.10.25019 版
%n.c
microsoft (r) incremental linker version 14.10.25019.0
/out:%n.exe
%n.obj
執行:%n
,結果:
為什麼我這裡執行異常呢?
結果都是正常。
五 如何解決「invalid parameter passed to c runtime function」?
最後我的注意力轉移到如何解決「 invalid parameter passed to c runtime function.」這個問題上來了。
於是,我又跑到stack overflow上尋找答案了。how-to-debug-invalid-parameter-passed-to-c-runtime-function
第乙個答案建議用gcc 配合選項進行設定除錯命令。我試了乙個用c99標準和c11標準,竟然都可以成功執行!
gcc -g %n.c -o %n_c99 -std=c99
%n_c99
blah blah
val = 5
hello: foo
bargcc -g %n.c -o %n_c11 -std=c11
%n_c11
blah blah
val = 5
hello: foo
bar
但是單純的不加選項,就不能成功執行。
接著我找到了:warning-invalid-parameter-passed-to-c
按照裡面的方式,我設定了斷點並run:
(gdb) b outputdebugstringa
(gdb) r
starting program: c:\users\\desktop/%n_.exe
[new thread 2748.0x26d8]
[new thread 2748.0x167c]
breakpoint 1, 0x773cb540 in outputdebugstringa () from c:\windows\syswow64\kernelbase.dll
(gdb) bt
#00x773cb540 in outputdebugstringa () from c:\windows\syswow64\kernelbase.dll
#10x7634811f in msvcrt!_invalid_parameter () from c:\windows\syswow64\msvcrt.dll
#20x762f5a40 in wctype () from c:\windows\syswow64\msvcrt.dll
#30x00010001 in ?? ()
#40x7636a9b7 in vswprintf () from c:\windows\syswow64\msvcrt.dll
#50x7636419b in printf () from c:\windows\syswow64\msvcrt.dll
#60x763a2628 in msvcrt!_iob () from c:\windows\syswow64\msvcrt.dll
#70x00405064 in __register_frame_info ()
#80x00401482 in main () at %n.c:7
看來問題比想象中複雜。我的初步猜想是window環境下c語言在某些版本中,不允許 在printf中使用%n對於有符號整數的賦值。把這個問題放在這裡,希望以後隨著能力的增長,能夠解決。 DebugPrint 格式說明符
1 直接列印字串。dbgprint hello world 2 空結尾的字串,你可以用普通得c 語法表示字串常量 char variable string hello world dbgprint s variable string 3 空結尾的寬字串 wchar 型別 wchar string w...
c 格式說明符
結構體變數用 運算子來訪問結構體的成員 指向結構體的指標用 來訪問其指向的結構體的成員 c 字元 d 十進位制整數 e 浮點數,指數e的形式 s 字串 e 浮點數,指數e的形式 u 無符號十進位制整數 f 浮點數,小數點形式 g 輸出 f與 e較短者 o 無符號八進位制整數 g 輸出 f與 e較短者...
匹配printf 說明符的型別
第1問題 列印結果如下 通常,在程式 中使用2345這樣的數字時,它以int型別儲存。當使用1000000這樣的數字int型別不能表示時,編譯器會視為long int型別 假定這種型別可以表示該數字 如果數字大於long型別的最大值,c會視其為unsigned long型別。如果仍然不夠,c會視其為...