printf 中 n格式說明符

2021-08-03 07:26:23 字數 3800 閱讀 7596

一 遇到%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會視其為...