到目前为止在snprintf中写的字符

Tal*_* A. 7 c gcc c99 format-string

最近,我注意到一个我想验证的奇怪案例:

通过SUS,对于%n格式字符串,各自int将被设置为写入到输出的字节量.此外,因为snprintf(dest, 3, "abcd"),dest将指向"ab\0".为什么?因为不要将n(n = 3)个字节写入输出(dest缓冲区).

我推断出代码:

int written;
char dest[3];
snprintf(dest, 3, "abcde%n", &written);
Run Code Online (Sandbox Code Playgroud)

written将被设置为2(从计数中排除的空终止).但是,根据我使用GCC 4.8.1进行的测试,written设置为5.我是否误解了标准?这是一个错误吗?是不确定的行为?

编辑:

@wildplasser说:

...格式字符串中%n的行为可能是未定义的或实现定义的......

...实现必须模拟处理完整的格式字符串(包括%n)...

@par说:

written是5,因为这是在%n遇到的点处写入的字符数.这是正确的行为. snprintf只复制到size字符减去尾随空格...

和:

另一种看待这种情况的方法是,%n如果它最多只处理2个字符就不会遇到,所以可以想象期望written有一个无效的值......

和:

...整个字符串通过printf()规则处理,然后应用max-length ...

是否可以通过标准,标准草案或某些官方来源进行验证?

par*_*par 7

written是5,因为这是在%n遇到的点处写入的字符数.这是正确的行为. snprintf只复制到size字符减去尾随空值(所以在你的情况下3-1 == 2.你必须将字符串格式化行为与only-write-so-many字符分开.

另一种看待这种情况的方法是,%n如果它最多只处理2个字符就不会遇到,所以可以想象期望written有一个无效的值.那就是会有一个错误的地方,如果你在某个written时候%n遇到了有效的东西(而且没有).

所以请记住,整个字符串是通过printf()规则处理的,然后应用max-length.


Gia*_*llo 5

这不是一个错误:ISOC99说

snprintf函数相当于fprintf [...]输出超出n-1的字符被丢弃而不是被写入数组[...]

所以它只是丢弃尾随输出,但在其他方面表现相同.