IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

C Discussion :

ANSI C strncat et \0 final


Sujet :

C

  1. #1
    Membre éprouvé
    Profil pro
    Inscrit en
    Octobre 2002
    Messages
    956
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2002
    Messages : 956
    Points : 1 199
    Points
    1 199
    Par défaut ANSI C strncat et \0 final
    Bonjour,
    Peut-on être sûr d'avoir un \0 final après un strncat et ce d'après la norme.
    Ma question ne porte pas sur telle ou telle implémentation de la norme par tel compilateur, mais est-ce qu'il est précisé dans la norme quelquechose concernant \0 final.
    Par exemple
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    char machaine1[20];
    char machaine2[20];
    strcpy(machaine1,"ABCDEF");
    strcpy(machaine2,"123456789A12345");
    strncat(machaine1,machaine2,3);
    Dans ce cas est-on sûr d'avoir un \0 en fin de chaine ou doit-on par sécurité l'ajouter.

    Je viens récemment de me fourvoyer avec strncpy, je voudrais savoir, si le risque est le même avec strncat.

    PS : J'ai cherché sur internet et sur le forum, mais j'ai trouvé des informations contradictoire :
    a / on ne peut pas être certain d'avoir un \0
    b/Il y a un \0 final
    c/ce n'est pas précisé.
    PPS: Je développe en C sous VMS, unix et windows avec le même code et des compilateurs différents.
    Cordialement
    Soazig

  2. #2
    Rédacteur

    Avatar de gege2061
    Femme Profil pro
    Administrateur de base de données
    Inscrit en
    Juin 2004
    Messages
    5 840
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Administrateur de base de données

    Informations forums :
    Inscription : Juin 2004
    Messages : 5 840
    Points : 11 625
    Points
    11 625
    Par défaut
    Bonjour,

    Citation Envoyé par soazig
    Peut-on être sûr d'avoir un \0 final après un strncat et ce d'après la norme.
    Non, il sera ajouté s'il reste de la place (que le résultat de la concaténation est inférieur à la taille passée en paramètre). Il faut faire ceci pour être tranquille :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    strncat (ch1, ch2, size);
    ch1[size-1] = '\0';

  3. #3
    Expert éminent sénior
    Avatar de Emmanuel Delahaye
    Profil pro
    Retraité
    Inscrit en
    Décembre 2003
    Messages
    14 512
    Détails du profil
    Informations personnelles :
    Âge : 67
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2003
    Messages : 14 512
    Points : 20 985
    Points
    20 985
    Par défaut
    Citation Envoyé par soazig
    Peut-on être sûr d'avoir un \0 final après un strncat
    Oui :
    Citation Envoyé par N1124
    7.21.3.2 The strncat function

    Synopsis

    1 #include <string.h>
    char *strncat(char * restrict s1, const char * restrict s2, size_t n);

    Description

    2 The strncat function appends not more than n characters (a null character and characters that follow it are not appended) from the array pointed to by s2 to the end of the string pointed to by s1. The initial character of s2 overwrites the null character at the end of s1. A terminating null character is always appended to the result.264) If copying takes place between objects that overlap, the behavior is undefined.

    Returns

    3 The strncat function returns the value of s1.

    -----------------------------------------------------
    264) Thus, the maximum number of characters that can end up in the array pointed to by s1 is strlen(s1)+n+1.
    Pas de Wi-Fi à la maison : CPL

  4. #4
    Expert éminent sénior
    Avatar de Emmanuel Delahaye
    Profil pro
    Retraité
    Inscrit en
    Décembre 2003
    Messages
    14 512
    Détails du profil
    Informations personnelles :
    Âge : 67
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2003
    Messages : 14 512
    Points : 20 985
    Points
    20 985
    Par défaut
    Citation Envoyé par gege2061
    Non, il sera ajouté s'il reste de la place
    Non, tu confonds avec strncpy().

    (la remarque N1124.263 concerne strncpy() et non strncat(). J'ai failli aussi me faire piéger)
    Pas de Wi-Fi à la maison : CPL

  5. #5
    Expert confirmé
    Avatar de Thierry Chappuis
    Homme Profil pro
    Enseignant Chercheur
    Inscrit en
    Mai 2005
    Messages
    3 499
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : Suisse

    Informations professionnelles :
    Activité : Enseignant Chercheur
    Secteur : Industrie Pharmaceutique

    Informations forums :
    Inscription : Mai 2005
    Messages : 3 499
    Points : 5 360
    Points
    5 360
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    char *strncat (char *dest, const char *src, size_t n);
    Cette fonction écrase le caractère nul de dest avec le premier caractère de src. Cette fonction copie au plus les n premiers caractères de src et ajoute '\0' à la suite. Ainsi, il faut faire attention.

    Imaginons que la chaîne dest passée en premier argument de la fonction soit vide et que tu écris:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    #include <string.h>
    /*...*/
    char s_buffer[11];
    /*...*/
    buffer[0] = '\0';
    strncat(s_buffer, "Hello world", sizeof s_buffer);
    La chaîne contenue dans s_buffer ne contiendra pas le caractère '\0' final, ou plutôt, elle le contiendra, mais ce dernier aura été ajouté hors des limites du tableau de caractères (à la position s_buffer[sizeof s_buffer]). La syntaxe correcte est donc:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    buffer[0] = '\0';
    strncat(s_buffer, "Hello world", sizeof s_buffer - 1);
    Dans ce cas, strncat est sûre et la chaîne contenue dans s_buffer se termine toujours avec le caractère '\0'.

    Maintenat, si s_buffer contient initialement déjà une chaîne de caractère, la manière de faire correcte est:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    #include <string.h>
    /*...*/
    char s_buffer[11] = "Hello ";
    strncat(s_buffer, "world", sizeof s_buffer - strlen(s_buffer) - 1);
    Le comportement de la fonction strncat n'est pas très cohérent avec la fonction fgets, par exemple, (char * fgets (char * s, int size, FILE * stream)) qui copie au plus size -1 caractère depuis le flux stream dans s, et qui place le caractère nul terminal. Je ne sais pas pourquoi strncat se comporte d'une manière différente, mais bon...

    Thierry
    "The most important thing in the kitchen is the waste paper basket and it needs to be centrally located.", Donald Knuth
    "If the only tool you have is a hammer, every problem looks like a nail.", probably Abraham Maslow

    FAQ-Python FAQ-C FAQ-C++

    +

  6. #6
    Membre éprouvé
    Profil pro
    Inscrit en
    Octobre 2002
    Messages
    956
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2002
    Messages : 956
    Points : 1 199
    Points
    1 199
    Par défaut
    Merci à tous.
    Donc si je résume, on est sûr d'avoir un \0 dans la chaine après appel à strncat, il est de la responsabilité du programmeur de se débrouiller pour que l'\0 se trouve dans le tableau de char alloué à la chaine et pas après.

    Merci de votre aide.
    Soazig

  7. #7
    Expert éminent sénior
    Avatar de Emmanuel Delahaye
    Profil pro
    Retraité
    Inscrit en
    Décembre 2003
    Messages
    14 512
    Détails du profil
    Informations personnelles :
    Âge : 67
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2003
    Messages : 14 512
    Points : 20 985
    Points
    20 985
    Par défaut
    Citation Envoyé par soazig
    Donc si je résume, on est sûr d'avoir un \0 dans la chaine après appel à strncat, il est de la responsabilité du programmeur de se débrouiller pour que l'\0 se trouve dans le tableau de char alloué à la chaine et pas après.
    Exactement.
    Pas de Wi-Fi à la maison : CPL

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Java EE 5 en version finale
    Par Petrus dans le forum Java EE
    Réponses: 12
    Dernier message: 13/05/2006, 16h01
  2. Norme SQL ansi 92
    Par Superstivix dans le forum Langage SQL
    Réponses: 8
    Dernier message: 22/02/2004, 15h44
  3. [débutant]portabilité de l'exe final
    Par vvidal80 dans le forum MFC
    Réponses: 8
    Dernier message: 07/01/2004, 09h21
  4. positionnement curseur et code ansi
    Par coach dans le forum C
    Réponses: 7
    Dernier message: 03/11/2003, 23h32
  5. Programmation ANSI C++ ou Borland C++ ?
    Par scarabee dans le forum C++Builder
    Réponses: 5
    Dernier message: 04/11/2002, 19h00

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo