Cosa succede se dimentico di chiudere un set?

Supponiamo che mi sia dimenticato di chiudere la parentesi quadra destra di un set. Cosa succederà allora? Invoca il comportamento indefinito?

Esempio:

 char str[] = "Hello! One Two Three"; char s1[50] = {0}, s2[50] = {0}; sscanf(str, "%s %[^h", s1, s2); /* UB? */ printf("s1='%s' s2='%s'\n", s1, s2); 

Ricevo un avviso da GCC durante la compilazione:

 source_file.c: In function 'main': source_file.c:11:5: warning: no closing ']' for '%[' format [-Wformat=] sscanf(str, "%s %[^h", s1, s2); /* UB? */ 

e l’output come

 s1='Hello!' s2='' 

Ho anche notato che sscanf restituisce 1. Ma cosa sta succedendo esattamente qui?

Ho controllato lo standard C11, ma non ho trovato alcuna informazione relativa a questo.

Eccellente! Dovresti presentare un rapporto sui difetti per C11!

Ecco la parte rilevante in C11 7.21.6.2

Lo specificatore di conversione include tutti i caratteri successivi nella stringa di formato, fino alla parentesi quadra destra corrispondente (]). I caratteri tra parentesi (la lista di scansione) compongono lo scanset, a meno che il carattere dopo la parentesi di sinistra non sia un circonflesso (^), nel qual caso l’insieme contiene tutti i caratteri che non compaiono nell’elenco di scansione tra il circonflesso e il arm destro.

Un’interpretazione rigorosa dei caratteri tra parentesi è che in assenza di una parentesi di chiusura non ci sono tali personaggi, ma in presenza di ^ come primo carattere dopo [ , sarebbe incoerente. gcc è abbastanza gentile da indicare il probabile errore nel codice sorgente. Il comportamento effettivo è determinato dall’implementazione della libreria C, ma non sembra essere specificato nello standard C. In quanto tale, è una forma di comportamento indefinito che IMHO dovrebbe essere realmente documentato come tale nello Standard.