As is mentioned by the other answers NULL
is not valid to pass to sscanf
as an additional argument.
http://www.cplusplus.com/reference/cstdio/sscanf says of additional arguments:
Depending on the format string, the function may expect a sequence of additional arguments, each containing a pointer to allocated storage where the interpretation of the extracted characters is stored with the appropriate type.
For the %s
specifier these extracted characters are:
Any number of non-whitespace characters, stopping at the first whitespace character found. A terminating null character is automatically added at the end of the stored sequence.
So when the "non-whitespace characters" and "terminating null character" is stored, there will be a segfault. Which is exactly what Visual Studio will yield (you can test that this fails at http://webcompiler.cloudapp.net/):

Now as far as non-Visual Studio compilers, libc's extraction code for the %s
specifier: https://github.com/ffainelli/uClibc/blob/master/libc/stdio/_scanf.c#L1376 has the leading comment: /* We might have to handle the allocation ourselves */
this is because:
The GNU C library supported the dynamic allocation conversion specifier (as a nonstandard extension) via the a
character. This feature seems to be present at least as far back as glibc 2.0.
Since version 2.7, glibc also provides the m
modifier for the same purpose as the a
modifier.
[Source]
So because libc extracts to a buffer constructed internally to sscanf
and subsequently checks that the buffer parameter has no flags set before assigning it, it will never write characters to a NULL
buffer parameter.
I can't stress enough that this is non-standard, and is not guaranteed to be preserved even between minor library updates. A far better way to do this is to use the *
sub-specifier which:
Indicates that the data is to be read from the stream but ignored (i.e. it is not stored in the location pointed by an argument).
[Source]
This could be accomplished like this for example:
s == NULL ? sscanf("Privjet mir!", "%*s") : sscanf("Privjet mir!", "%s", s);
Obviously the true-branch of the ternary is a no-op, but I've included it with the expectation that other data was expected to be read from the string.