2016-11-27 3 views
0
int main() { 
    char src[] = "santosh"; 
    char dest[0]; 
    strncpy(dest, src, 4); 
    printf("%s\n", dest); // expecting o/p "sant" but o/p was "santtosh" 
    int i = 0; 
    while (dest[i]) { 
     printf("%c", dest[i]); //expecting output "sant" but it was "santtosh" 
     i++; 
    } 

    printf("\n"); 
    i = 0; 

    while (src[i]) { 
     printf("%c", src[i]); // expecting o/p "santosh" but it was "anttosh" 
     i++; 
    } 
    return 0; 
} 

J'ai des problèmes avec ce code, je cours le code en utilisant le compilateur gcc et voici la sortie que j'ai (section commentaire). Pourquoi le comportement n'est pas conforme à l'attente? pourquoi strncpy() est capable de copier la chaîne source même si le buff de destination n'est pas suffisant?pourquoi strncpy est capable de copier la chaîne source même si le tampon de destination est zéro?

+5

'char dest [0] '<- à peu près votre programme entier est un comportement non défini à ce stade. Ce que vous dites avec cette déclaration est que le tableau 'dest' est une taille * fixe * de 0 caractères. Par conséquent, il ne peut jamais contenir quoi que ce soit et tout accès (lecture * ou * écriture) est indéfini. –

+2

Nommé d'après un groupe pop britannique ** UB40 ** ... Vous devriez également envisager de supprimer la balise 'C++'. –

+1

C'est un comportement indéfini. C vous laissera écrire où vous voulez, et c'est à vous de décider si vous devriez ... – Charles

Répondre

1

Votre code invoque un comportement indéfini, en essayant d'expliquer pourquoi il produit une sortie ou un autre est inutile.

Voici les problèmes:

  • Vous ne contient pas <stdio.h>, ni <string.h>. L'appel de fonctions qui n'ont pas été définies précédemment n'est pas OK. Incluez le fichier d'en-tête approprié pour éviter un comportement indéfini.

  • char dest[0]; définit un tableau avec une taille de 0. Un tel objet n'est pas accessible, pas même son adresse est significative. gcc et clang permettent cela, mais comme une extension de la norme C. Cette définition ressemble à une faute de frappe, utilisez gcc -Wall -W ou clang -Weverything pour activer les avertissements utiles qui permettront d'éviter de tels bogues stupides.

  • strncpy(dest, src, 4); invoque un comportement indéfini puisque la longueur de dest est inférieure à 4. Notez que le comportement serait toujours sujet à erreur si dest avait une longueur de 4 puisque strncpy ne terminerait pas le tableau de destination si la longueur de la chaîne source est supérieure ou égale à l'argument size. Ici "santosh" a une longueur de 7, donc dest contiendrait les caractères s, a, n et t, mais pas de terminateur nul. Votre boucle while invoquerait un comportement indéfini car while (dest[i]) accéderait dest au-delà de sa taille. strncpy() est sujet à erreur, sa sémantique est largement méconnue et cause des bogues très facilement. N'utilisez pas cette fonction.

  • Comme expliqué plus haut, un comportement non défini while (dest[i]) invoque parce que dest ne peut pas être déréférencé telle que définie actuellement ou même si elle était définie comme char dest[4];.

Voici une version améliorée, en utilisant snprintf() et strncat():

#include <stdio.h> 
#include <string.h> 

int main(void) { 
    char src[] = "santosh"; 
    char dest[5]; 

    *dest = '\0'; 
    strncat(dest, src, 4); 
    printf("%s\n", dest);  // will output "sant" 
    for (int i = 0; dest[i]; i++) { 
     printf("%c", dest[i]); // will output "sant" too 
    } 
    printf("\n"); 

    snprintf(dest, sizeof dest, "%s", src); 
    printf("%s\n", dest);  // will output "sant" 
    for (int i = 0; dest[i]; i++) { 
     printf("%c", dest[i]); // will output "sant" again 
    } 
    printf("\n"); 

    for (int i = 0; src[i]; i++) { 
     printf("%c", src[i]); // will output "santosh" 
    } 
    printf("\n"); 

    return 0; 
}