printf()中%n格式说明符

来源:互联网 发布:dede cms 排行榜文章 编辑:程序博客网 时间:2024/05/29 05:01

一 遇到%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 <stdio.h>int main(){  int val;  printf("blah %n blah\n", &val);  printf("val = %d\n", val);  return 0;}

结果是:

blah  blahval = 5

第二个答案给了另一个例子:

int n;printf("%s: %nFoo\n", "hello", &n);printf("%*sBar\n", n, "");

结果是:

hello: Foo       Bar

三 我的运行异常和调试情况

我决定手动运行一下。

我的程序如下:

#include <stdio.h>int main(void) {    /* test 1*/    int val;    printf("blah %n blah\n", &val);    printf("val = %d\n", val);    /* test 2*/    int n;    printf("%s: %nFoo\n", "hello", &n);    printf("%*sBar\n", n, "");    return 0;}

我先用MinGW的gcc进行编译运行:

gcc -g %n.c -o %n

结果运行时,一直在打印空格,控制台旁边的滑块迅速向下滑行,过了好一会才有字符出现。

我试着用gdb进行调试:

7               printf("blah %n blah\n", &val);(gdb) p val$1 = 4194432(gdb) nwarning: 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 版版权所有(C) Microsoft Corporation。保留所有权利。%n.cMicrosoft (R) Incremental Linker Version 14.10.25019.0Copyright (C) Microsoft Corporation.  All rights reserved./out:%n.exe%n.obj

运行:%n ,结果:
停止工作


四 用在线IDE进行测试

为什么我这里运行异常呢?

我另外找了两个在线IDE测试。以下是截图:

1、http://ide.geeksforgeeks.org/

Web IDE test1

2、http://codepad.org
Web IDE test2

结果都是正常。


五 如何解决“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_c99blah  blahval = 5hello: Foo       Bargcc -g %n.c -o %n_c11 -std=c11%n_c11blah  blahval = 5hello: Foo       Bar

但是单纯的不加选项,就不能成功运行。

接着我找到了:warning-invalid-parameter-passed-to-c

按照里面的方式,我设置了断点并run:

(gdb) b OutputDebugStringA(gdb) rStarting 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#0  0x773cb540 in OutputDebugStringA () from C:\WINDOWS\SysWOW64\KernelBase.dll#1  0x7634811f in msvcrt!_invalid_parameter () from C:\WINDOWS\SysWOW64\msvcrt.dll#2  0x762f5a40 in wctype () from C:\WINDOWS\SysWOW64\msvcrt.dll#3  0x00010001 in ?? ()#4  0x7636a9b7 in vswprintf () from C:\WINDOWS\SysWOW64\msvcrt.dll#5  0x7636419b in printf () from C:\WINDOWS\SysWOW64\msvcrt.dll#6  0x763a2628 in msvcrt!_iob () from C:\WINDOWS\SysWOW64\msvcrt.dll#7  0x00405064 in __register_frame_info ()#8  0x00401482 in main () at %n.c:7

看来问题比想象中复杂。我的初步猜想是Window环境下C语言在某些版本中,不允许 在printf中使用%n对于有符号整数的赋值。把这个问题放在这里,希望以后随着能力的增长,能够解决。

原创粉丝点击