C99 草案标准没有明确说明在这些情况下应该发生什么,但是通过考虑多种变化,您可以表明它必须以某种方式工作,以便在所有情况下都符合规范。
标准说:
%s - 匹配一系列非空白字符。252)
如果不存在 l 长度修饰符,则相应的参数应是指向字符数组的初始元素的指针,该元素数组的大小足以接受序列和终止空字符,它将自动添加。
这是一对示例,表明它必须按照您建议的方式工作才能满足标准。
示例 A:
char buffer[4] = "abcd";
char buffer2[10]; // Note the this could be placed at what would be buffer+4
sscanf("123 4", "%s %s", buffer, buffer2);
// Result is buffer = "123\0"
// buffer2 = "4\0"
示例 B:
char buffer[17] = "abcdefghijklmnop";
char* buffer2 = &buffer[4];
sscanf("123 4", "%s %s", buffer, buffer2);
// Result is buffer = "123\04\0"
请注意, sscanf 的接口没有提供足够的信息来真正知道它们是不同的。因此,如果示例 B 要正常工作,它不能与示例 A 中的空字符后面的字节混淆。这是因为它必须根据这一规范在两种情况下都工作。
因此,由于规范,它必须按照您所说的那样工作。
可以为其他函数放置类似的参数,但我认为您可以从这个示例中看到这个想法。
注意:以“%16s”等格式提供大小限制可能会改变行为。根据规范, sscanf 在将数据写入缓冲区之前将缓冲区归零到其限制在功能上是可以接受的。在实践中,大多数实现选择性能,这意味着它们不理会其余部分。
当规范的意图是进行这种归零时,通常会明确指定。strncpy 就是一个例子。如果字符串的长度小于指定的最大缓冲区长度,它将用空字符填充剩余的空间。这个相同的“字符串”函数也可以返回一个未终止的字符串,这一事实使得它成为人们推出自己的版本的最常见的函数之一。
就 fgets 而言,可能会出现类似的情况。唯一的问题是规范明确指出,如果没有读入,缓冲区保持不变。一个可接受的功能实现可以通过在清零缓冲区之前检查是否至少有一个字节要读取来回避这一点。