Come è menzionato dalle altre risposte NULL
non è valida per passare a sscanf
come un ulteriore argomento.
http://www.cplusplus.com/reference/cstdio/sscanf dice di ulteriori argomenti
seconda della stringa di formato, la funzione può aspettarsi una sequenza di argomenti aggiuntivi, ciascuno contenente un puntatore di memoria allocata quando l'interpretazione dei caratteri estratti viene memorizzata con il tipo appropriato.
For the %s
specifier these extracted characters are:
qualsiasi numero di caratteri che non sono spazi, fermandosi al primo carattere spazio bianco trovato. Un carattere nullo terminante viene aggiunto automaticamente alla fine della sequenza memorizzata.
Così quando sono memorizzati i "caratteri non di spaziatura" e "carattere nullo di fine", ci sarà un segfault. Il che è esattamente ciò che Visual Studio produrrà (è possibile verificare che questo non riesce a http://webcompiler.cloudapp.net/):
Ora per quanto non Visual Studio compilatori, il codice di estrazione di libc per la %s
identificatore: https://github.com/ffainelli/uClibc/blob/master/libc/stdio/_scanf.c#L1376 ha il leader commento: /* We might have to handle the allocation ourselves */
questo perché:
la libreria GNU C supportato l'indicatore di conversione allocazione dinamica (come estensione non standard) tramite il carattere a
. Questa funzione sembra essere presente almeno fino a quella di glibc 2.0.
Dalla versione 2.7, glibc fornisce anche il modificatore m
per lo stesso scopo del modificatore a
.
[Source]
Quindi, a causa estratti libc ad un buffer costruiti internamente per sscanf
e, successivamente, controlla che il parametro di buffer non ha bandiere impostato prima di assegnarlo, non potrà mai scrivere i caratteri di un parametro NULL
buffer.
Non posso sottolineare abbastanza che questo non è standard e non è garantito che venga mantenuto anche tra gli aggiornamenti di librerie minori. Un modo di gran lunga migliore per farlo è quello di utilizzare la *
sub-specificatore cui:
Indica che i dati devono essere letti dal flusso ma ignorato (cioè non viene memorizzato nella posizione indicata da un argomento) .
[Source]
Ciò potrebbe essere realizzato in questo modo, per esempio:
s == NULL ? sscanf("Privjet mir!", "%*s") : sscanf("Privjet mir!", "%s", s);
Ovviamente il vero ramo del ternario è un no-op, ma ho incluso con l'aspettativa che altri dati dovessero essere letti dalla stringa.
Questa risposta ci insegna anche che proibire null non ha bisogno di menzionare esplicitamente la parola "null".Affermando che qualcosa deve essere "un puntatore a" vieta implicitamente il nulla. –
Lii