在C语言标准的哪一条规定,fscanf中 %n的对应参数应为指向int的指针?
C23标准草案n3220对语句7.23.6.2p12中的转换说明符 n 针对 fscanf 有如下描述( emphasis mine )
n不会消耗输入。 相应的参数应为一个指向带符号整型的指针。 到目前为止,由此次对fscanf函数的调用从输入流中读取的字符数被存储到参数所指向的整型对象中。 执行 %n指令不会增加在fscanf函数执行完成时返回的赋值计数。没有转换任何参数,但有一个被消耗。如果转换说明符包含一个赋值抑制字符或字段宽度,行为未定义。
我没有看到对转换说明符 %n(没有长度修饰符)的相应参数应为指向 int 的指针的描述。
因此,下面的程序应该是定义良好的,因为 long long int 是带符号整型。
#include <stdio.h>
int main(void){
long long n = -1;
char c;
int num_asn = sscanf("...h", "...%n%c", &n, &c);
printf("num_asn = %i\n", num_asn);
printf("n = %lli\n", n);
printf("c = %c\n", c);
}
我用 gcc main.c -std=c23 编译了这个程序,并与 cygwin C库链接。
我期望得到如下输出:
num_asn = 1
n = 3
c = h
然而,我收到如下输出
num_asn = 1
n = -4294967293
c = h
当我把程序中的 n 改为 int 的类型时,我得到了预期的输出。
Example 4, in statement 7.23.6.2p21, in the C23 standard draft n3220, uses a pointer to int for conversion specification %n but doesnt say why:
#include <stdio.h>
/* ... */
int d1, d2, n1, n2, i;
i = sscanf("123", "%d%n%n%d", &d1, &n1, &n2, &d2);
在C23草案(或C 标准的任何修订版)中,在哪里提到转换说明符 %n 的相应参数应为指向 int 的指针,用于 fscanf?
解决方案
Where in the C23 draft (or in any C standard) does it mention the corresponding argument for the conversion specification
%nshall be a pointer toint
确切的类型由长度修饰符规定,如7.23.6.2p11节所述。它指出,hh、h、l、ll、j、t、z 修饰符可以应用于 n 的格式说明符,以指示参数分别指向 char、short、long、long long、intmax_t、ptrdiff_t、size_t。
从C23开始,d、i、o、u、x 这几个格式说明符的文档被更新(并新增了 b),以明确说明缺少长度修饰符时,参数是 int * 或 unsigned int *。在此之前,它们与 n 相同,因为未明确说明这一点。
鉴于7.23.6.2p11指出长度修饰符对 n 的作用至少可追溯到C11,同时 d、i、o、u、x 的文档也已更新,这很可能是一个疏漏。
如果你的代码把 %lln 作为完整的格式说明符,你本应得到预期结果。