Comportement étrange de sscanf avec une chaîne

J’ai un problème avec sscanf . Pour le vérifier, j’ai créé un fichier simple, donc quand je comstack ceci:

 #include  main(){ char *a; /* */ char *s = "GET /something HTTP/1.1\r\n"; printf("sscanf: %d\n", sscanf(s, "GET %s HTTP", a)); printf("a: %s\n", a); /* */ printf("sscan: %d\n", sscanf("GET /more HTTP/1.1\r\n", "GET %s HTTP", a)); printf("a: %s\n", a); } 

Je reçois la bonne sortie:

 sscanf: 1 a: /something sscan: 1 a: /more 

Mais quand je commente des lignes entre des commentaires vides, je reçois:

 sscan: 0 a: (null) 

Question 1 : Comment peut-il en être ainsi?

Et un peu plus: si j’écris char *a = NULL , je reçois:

 sscanf: 0 a: (null) sscan: 0 a: (null) 

Question 2 : pourquoi?

Vous copiez une chaîne vers un pointeur non initialisé ( a ). Vous devez lui allouer de l’espace de stockage (avec malloc ) ou déclarer un tableau.

Les implémentations peuvent parfois sembler fonctionner correctement lorsque vous n’allouez aucun stockage. Lorsque vous affectez NULL à a , sscanf ne stocke rien et vous essayez donc d’imprimer une “chaîne” avec un pointeur NULL ( printf imprimé sous la forme (null) ). Sur certains systèmes, votre programme planterait tout simplement.

Il existe une extension compilateur / bibliothèque qui permet l’allocation automatique de chaînes, mais ce n’est évidemment pas portable et tous les compilateurs ne le prennent pas en charge.

 char *a; scanf("%ms", &a;) // allocates storage for a 

Vous pouvez passer un pointeur non initialisé à la fonction, mais notez le & .

Vous passez un pointeur non initialisé à sscanf. change char *a; pour char a[100] et cela devrait fonctionner correctement.

Vous écrivez des données dans un espace non alloué. char *a; est seulement un pointeur sur la mémoire aléatoire. Après avoir essayé de placer des données dans votre “chaîne”, vous invoquez un comportement indéfini et tout peut arriver.

Eh bien, la seule bonne chose dans mon cas, comme je pense, serait la suivante:

 #include  #include  #include  main(){ char *s = strdup("GET /something HTTP/1.1\r\n"); char *a, *e, *ans; char *end = s + strlen(s); a = strstr(s, "GET"); if(!a) return -1; a += 4; if(a >= end) return -1; e = strstr(a, "HTTP/1.1"); if(!e) return -1; *(--e) = 0; ans = strdup(a); printf("ans: %s\n", ans); } 

Dans le cas courant, la chaîne s peut avoir une très grande taille, il serait donc préférable de ne pas allouer beaucoup de mémoire, mais d’allouer correctement, comme il me faut.

Le cas avec “% as” ne fonctionne pas avec mon gcc (4.7.2).