chaînes de différence de largeur fixe et chaînes terminées par zéro

gcc 4.4.4 c89

J’ai récemment eu une discussion sur les “chaînes de largeur fixe” et les “chaînes terminées par zéro”.

Quand je pense à ça. Ils semblent être la même chose. Une chaîne avec un null final.

c’est à dire

char *name = "Joe bloggs"; 

Est une chaîne de largeur fixe qui ne peut pas être modifiée. Et a également une terminaison nulle.

Au cours de la discussion, on m’a également dit que strncpy ne devrait jamais être utilisé sur des «chaînes terminées par un zéro».

Un grand merci pour toutes les suggestions,

Le terme “chaîne à largeur fixe” désigne généralement quelque chose de complètement différent.

Une chaîne de largeur fixe avec N est une chaîne d’exactement N caractères, où il est garanti que tous les N caractères sont initialisés. Si vous voulez représenter une chaîne plus courte, vous devez compléter votre chaîne avec zéro caractère à la fin. Vous devez append autant de caractères zéro que nécessaire pour utiliser tous les N caractères. Notez que si vous avez besoin de stocker une chaîne de longueur exactement N , une chaîne de largeur fixe n’aura pas de caractère zéro à la fin. C’est-à-dire qu’en général, les chaînes de largeur fixe ne sont pas terminées à zéro!

Quel est le but de ceci? Le but de ceci est de sauvegarder 1 caractère lorsque vous stockez la chaîne de longueur maximale possible. Si vous utilisez des chaînes de largeur N de largeur fixe, vous devez exactement N caractères pour représenter une chaîne de longueur N Comparez cela aux chaînes ordinaires terminées à zéro, qui nécessiteraient N + 1 caractère (caractère supplémentaire pour le terminateur zéro).

Pourquoi est-il rempli de zéros à la fin? Il est complété par des zéros pour simplifier la comparaison lexicographique des chaînes à largeur fixe. Vous comparez simplement tous les N caractères jusqu’à ce que vous trouviez la différence. Notez que vous pouvez utiliser absolument n’importe quel caractère pour compléter la chaîne de largeur fixe. Assurez-vous simplement que vous obtenez le bon ordre lexicographique. L’utilisation de zéro caractère pour le remplissage est cependant un bon choix.

Quand est-ce utile? Très rarement. Les économies fournies par les chaînes à largeur fixe sont rarement importantes pour le traitement générique des chaînes: elles sont trop petites et ne se produisent que dans les cas où la chaîne utilise la totalité de la largeur. Mais ils pourraient être utiles dans certains cas spécifiques.

D’où vient tout cela? Un exemple classique de “chaîne de largeur fixe” est un champ de nom de fichier large de 14 caractères dans une ancienne version du système de fichiers Unix. Il était représenté par un tableau de 14 caractères et une représentation à largeur fixe était utilisée. À ce moment, il était important d’économiser 1 caractère sur le nom de fichier complet (tous les 14 caractères).

Maintenant, pour strncpy . La fonction strncpy été spécifiquement introduite pour initialiser ces champs de nom de fichier larges de 14 caractères dans ce système de fichiers. La fonction strncpy été créée spécifiquement pour générer une chaîne valide à largeur fixe: elle convertit une chaîne terminée par zéro en chaîne à largeur fixe. Malheureusement, un nom trompeur lui a été atsortingbué, ce qui explique pourquoi de nombreuses personnes le confondent avec une fonction de copie “sûre” pour les chaînes terminées à zéro. Ce dernier est une compréhension totalement incorrecte du but et des fonctionnalités de strncpy .

Utiliser des littéraux de chaîne pour représenter des chaînes de largeur fixe (comme dans votre exemple) n’est pas une bonne idée, car les littéraux de chaîne ajoutent toujours un caractère zéro à la fin et les chaînes de largeur fixe ne le font pas nécessairement. C’est ainsi qu’un tas de chaînes de largeur fixe peut être initialisé dans un programme C

 char fw_ssortingng1[7] = { 'T', 'h', 'i', 's', ' ', 'i', 's' }; char fw_ssortingng2[7] = { 's', 't', 'r', 'i', 'n', 'g' }; char fw_ssortingng3[7] = { 'H', 'e', 'l', 'l', 'o' }; 

Tous les tableaux ont le même nombre d’éléments – 7. Notez que la première chaîne n’est pas terminée par un zéro, alors que les autres sont complétées par un zéro. La conversion de chaîne “ordinaire” en chaîne à largeur fixe se présentera comme suit

 char fw_ssortingng4[7]; strncpy(fw_ssortingng4, "Hi!", 7); 

Dans ce cas, la fonction strncpy est utilisée exactement à quoi elle était destinée.

N’oubliez pas non plus qu’en dehors de la fonction de conversion strncpy , la bibliothèque standard ne fournit pratiquement aucun moyen de travailler avec des chaînes à largeur fixe. Vous devez essentiellement les traiter comme des tableaux de caractères bruts et implémenter manuellement les opérations de niveau supérieur. La plupart des opérations de base seront naturellement implémentées par les fonctions de mem... group. memcmp , par exemple, implémentera la comparaison.

PS En fait, en tenant compte du commentaire de caf, en langage C, on peut utiliser des littéraux de chaîne pour initialiser des chaînes de largeur fixe, car le langage C permet à l’initialiseur de littéraux d’être un caractère plus long que le tableau (c’est-à-dire en C ne rentre pas dans le tableau). Donc, ce qui précède peut être réécrit de manière équivalente en tant que

 char fw_ssortingng1[7] = "This is"; char fw_ssortingng2[7] = "ssortingng"; char fw_ssortingng3[7] = "Hello"; 

Notez que fw_ssortingng1 n’est toujours pas terminé par zéro dans ce cas.

Tout d’abord, je pense que vous entendez une chaîne de longueur fixe et non une chaîne.

Deuxièmement, ce qui précède est une chaîne terminée par un zéro. Il ne devrait pas être changé en raison de sa définition en tant que constante littérale.

Autant que je sache, C n’a pas de réelle “chaîne de longueur fixe”. Au mieux, vous pouvez définir un tampon de taille N et ne pas y placer plus de N-1 caractères. Placer plus serait une erreur et ne pas oublier le terminateur nul peut être une erreur.

Quant à strncpy, il copie le nombre de caractères spécifié et zéro le rest. Cela signifie que si la destination n’est pas assez longue, vous écririez au-delà de l’espace disponible ou n’auriez pas de terminateur nul pour votre chaîne, ce qui entraînerait des erreurs lorsque vous essayez d’utiliser la chaîne.

Je ne suis pas tout à fait sûr du terme «chaîne de largeur de réparation». En fonction de la fonction C, les chaînes ont besoin ou non d’une fin \ 0. Des fonctions telles que strlen et strcpy doivent fonctionner sur \ 0 chaînes terminées pour savoir quand s’arrêter. Des fonctions comme strncpy n’ont pas besoin que la chaîne source soit terminée par un 0. Un argument indique le nombre de caractères à copier.

Lorsque vous déclarez name comme vous le faites, le contenu de ce nom est stocké dans la mémoire en lecture seule et ne peut pas être modifié; toutefois, vous pouvez utiliser ‘name’ dans les fonctions C qui ne modifient pas le contenu, par exemple strlen (nom) ou utilisé en tant que source:

 char mycopy[32]; strcpy( mycopy, name );