Pourquoi le nom du personnage peut contenir plus d’un caractère?

Je faisais un peu de recherche sur un sujet lorsque je suis tombé sur cette situation. Supposons le code C suivant:

#include  int main() { char name[1]; scanf("%s",name); printf("Hi %s",name); return 0; } 

J’ai compilé avec -fno-stack-protector et testé avec une entrée plus longue que 1, comme John , et à ma grande surprise, ça marche!
Ne devrait-il pas émettre une erreur de segmentation lorsque l’entrée est supérieure à 1?
Finalement, cela a cassé avec Alexander comme entrée (9) mais cela fonctionne avec rien de moins que 9.
Pourquoi fonctionne-t-il avec des entrées plus longues que la longueur du tableau de noms?
PS: J’utilise Ubuntu (64 bits), la version 4.8.4 de gcc (Ubuntu 4.8.4-2ubuntu1 ~ 14.04) & CLion en tant qu’IDE.

    C’est un comportement indéfini. Votre programme a un dépassement de tampon, car il alloue exactement un caractère, ce qui est suffisant pour stocker une chaîne vide terminée par un zéro.

    Cependant, il existe une mémoire adjacente à votre tampon qui n’a pas été allouée à votre programme. scanf place votre entrée dans cette mémoire, car il ne sait pas combien de temps dure votre mémoire tampon de chaîne. C’est un grand danger et une source d’innombrables attaques de hackers, lorsqu’une séquence d’octets prédéterminée est placée dans votre chaîne, dans l’espoir de remplacer certains éléments vitaux et éventuellement de prendre le contrôle.

    C’est pourquoi utiliser %s sans spécifier la taille est dangereux. Vous devez toujours append une limite de taille appropriée à %s , sinon votre programme risque de saturation de la mémoire tampon.

     char name[120]; scanf("%119s",name); 

    Ce programme est sécurisé, car même si un utilisateur malveillant saisissait plus de 120 caractères, scanf ignorait tout ce qui se trouvait après le 119ème caractère, comme indiqué au format %119s .

    La taille et le type de la variable dans laquelle vous stockez l’entrée n’ont rien à voir avec scanf .

    scanf se voit uniquement transmettre une adresse (pointeur) où déposer les données qu’il reçoit de l’utilisateur.

    Des compilateurs intelligents vous avertissent maintenant si la chaîne de format transmise à scanf ne correspond pas au type des parameters, mais vous pouvez en principe même déclarer le name sous la forme d’un entier:

     int name; 

    et il tiendrait très bien la chaîne d’entrée, jusqu’à trois caractères (le quasortingème correspond à End Of Ssortingng, c’est-à-dire zéro), en supposant que la taille de int est de 32 bits, soit 4 octets.

    Le fait que cela fonctionne est un pur hasard, car les données d’entrée, lorsqu’elles sont stockées par scanf , scanf -delà de la fin du tampon alloué pour celle-ci ( name ).

    Remarque: l’atsortingbution d’un seul caractère à une chaîne ne fonctionnerait jamais, même pour les chaînes d’entrée d’un seul caractère. Vous devez toujours tenir compte de l’EOS utilisé pour les terminer. Donc, name devrait être déclaré comme char name[2]; tout au moins.