The C99 draft standard does not explicitly indicate what should happen in these cases, but by considering several options, you can show that it should work in a certain way, it meets the specification in all cases.
The standard says:
% s - Matches a sequence of non-white space characters .252)
If there is no modifier of length l, the corresponding argument must be a pointer to the source element of the character array large enough to accept a sequence and a terminating null character to be added automatically.
Here are a couple of examples that show this, should work as you suggest, in order to comply with the standard.
Example 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"
Example B:
char buffer[17] = "abcdefghijklmnop"; char* buffer2 = &buffer[4]; sscanf("123 4", "%s %s", buffer, buffer2);
Note that the sscanf interface does not provide enough information to really know that they were different. So, if Example B should work correctly, it should not mess up with bytes after the null character in Example A. This is because it should work in both cases in accordance with this specification bit.
So implicitly it should work, as you stated because of the spec.
Similar arguments can be placed for other functions, but I think you can see the idea from this example.
Note: Providing size limits in a format such as "% 16s" may change the behavior. By specification, it would be functionally acceptable for sscanf to zero the buffer to its limits before writing data to the buffer. In practice, most implementations choose performance, which means that they leave the rest.
When the purpose of the specification is to perform such a nulling, it is usually indicated explicitly. Strncpy example. If the line length is less than the specified maximum buffer length, it fills the rest of the space with null characters. The fact that this same “string” function can return a string endlessly also makes this one of the most common functions for people to collapse their own version.
As for fgets, a similar situation may arise. The only problem is that the specification explicitly states that if nothing is read, the buffer remains untouched. A valid functional implementation can work around this by checking if there is at least one byte to read before zeroing the buffer.