2011-08-13 4 views
1

autant que je sache, l'éditeur de liens tente de fusion deux littéraux de chaîne en un seul littéral, si elles sont à la fois la même chose, par exemple:chaîne C littéraux reliant

fichier1.c

char const* firstString = "foo"; 

file2.c

char const* secondString = "foo"; 

résulterait en une seule occurrence de foo\0 dans la section de mémoire respective (gain de 4 octets). Ceci est particulièrement important pour les applications embarquées (comment se comporte le avr-gcc par rapport au gcc). Mais je me demandais si je pouvais vraiment compter sur cela, et je suppose que si deux chaînes sont égales, leurs pointeurs sont égaux (à condition que dans tout le programme, vous ne passiez que des chaînes de caractères et pas d'exécution). les chaînes générées existent - ce qui est une hypothèse raisonnable dans mon cas). De toute évidence, je veux accélérer les comparaisons de vitesse avec cela, et permettre une fonction couramment utilisée pour recevoir une chaîne littérale comme ceci:

void lock(char const*); 
void unlock(char const*); 

lock("test"); 
dosmth(); 
unlock("test"); 

Essentiellement, je veux éviter un trop grand ENUM et d'énormes commutateurs à l'intérieur du lock/unlock fonctions.

+2

La norme C ne donne pas de telles garanties –

+0

Note: J'ai modifié la question pour indiquer que toutes les chaînes sont immuables. – bitmask

+0

L'utilisation de chaînes à cet effet est au-delà de la rupture. –

Répondre

1

L'éditeur de liens n'a rien à fusionner. Il suffit de mapper un type déclaré à un type défini. Cela implique de trouver le type défini et de remplir les décalages d'adresse pour passer au bon élément.

Ce dont vous parlez serait un éditeur de liens optimisant. De nombreux linkers n'optimisent pas du tout, et ceux qui le font ne sont pas maintenus à un standard d'optimisation, donc vous ne pourrez jamais généraliser au-delà des résultats observés pour le linker que vous découvrez (sur cette machine, à ce moment là).

3

En fait, ils ne peuvent pas pointer vers la même mémoire, puisque vous pouvez leur écrire.

Maintenant, si vous deviez dire:

char *s1 = "MyString"; 
char *s2 = "MyString"; 

alors il est en effet possible que s1 == s2. Ne pense pas que c'est garanti.

+0

Très bonne observation comme toujours. –

+0

Ils devraient être des chaînes constantes, ne devraient-ils pas? - Même je les jette dans une variable 'char []'; Les littéraux eux-mêmes sont 'const'. – bitmask

+1

Non seulement char * str = ... est constant. Lorsque vous faites l'initialisation comme vous l'avez fait, la chaîne est mutable. –

2

Je ne compterais probablement pas dessus car le compilateur dépend de la façon dont les symboles sont résolus comme ceci. La plupart des compilateurs créent une instance de la chaîne constante, puis la référencent simplement, mais je ne dépendrais pas de cela car il y a des cas où cela ne fonctionne pas. Personnellement, je n'utiliserais pas de chaînes comme celle-ci dans votre méthode de verrouillage et de déverrouillage. Un enum vous servira probablement mieux.

1

Je pense que vous êtes sur la mauvaise voie. Non seulement l'éditeur de liens ne fusionne pas les littéraux de chaîne provenant de différentes unités de compilation, mais il ne crée probablement pas de symbole externe pour eux.

Même à l'intérieur de la même unité de compilation, le compilateur peut fusionner deux occurrences de la même chaîne littérale en un seul, mais il est pas obligé de le faire:

Il est précisé si ces tableaux sont distincts à condition que leurs éléments aient les valeurs appropriées.

Maintenant, au vrai problème qui semble être à la source de votre question. Faire des verrous/déverrouiller des paires basées sur des littéraux de chaînes n'est probablement pas une bonne idée en C. Comme vous le dites, cela a tendance à gonfler votre code avec switch ou des choses similaires.

Plus naturel serait d'avoir un type de verrou et de déclarer une variable globale avec un nom distinctif pour chacun de vos événements distinctifs de verrouillage/déverrouillage. Cela vous oblige à déclarer chaque événement d'une manière visible dans toutes vos unités de compilation, et à choisir une unité de compilation où vous l'avez réellement définie.

Questions connexes