Question

Pourquoi name mal se comporte-t-il dans le code C ++ suivant?

string name =  "ab"+'c';

Comment le code équivalent se comporterait-il en Java / C #?

Était-ce utile?

La solution

Essayez

std::string name = "ab" "c";

ou

std::string name = std::string("ab") + c;

En C ++, " ab " n'est pas un std::string, mais plutôt un pointeur sur une chaîne de caractères. Lorsque vous ajoutez une valeur intégrale à un pointeur, vous obtenez un nouveau pointeur qui pointe plus bas dans la chaîne:

char *foo = "012345678910121416182022242628303234";
std::string name = foo + ' '; 

name est réglé sur & "3234 &" ;, étant donné que la valeur entière de '' est 32 et que 32 caractères après le début de foo sont quatre caractères avant la fin de la chaîne. Si la chaîne était plus courte, vous tenteriez d'accéder à quelque chose se trouvant dans un territoire mémoire non défini.

La solution à cela est de créer une chaîne std: string à partir du tableau de caractères. std: les chaînes vous permettent d’y ajouter des caractères comme prévu:

std::string foo = "012345678910121416182022242628303234";
std::string name = foo + ' '; 

<=> est réglé sur & "; 012345678910121416182022242628303234 &";

Autres conseils

Le problème est que " ab " n’est pas un C ++ std::string, mais un const char[3]. L’opérateur + recherché est donc operator+ (const char[3], char). Cela n'existe pas, le compilateur essaie de laisser le tableau se décomposer en un pointeur. Il recherche donc operator+ (const char*, char). Cela existe, donc le compilateur choisit cela, mais il fait la mauvaise chose. Ajouter une valeur intégrale (le caractère) à un pointeur (le caractère constant *) est une opération assez commune, et bien évidemment, c'est ce que cet opérateur + fait. La clé pour comprendre cela est de réaliser que le premier argument est 1) un tableau et 2) un pointeur chaque fois que le tableau n’a pas de sens. Il a également été utilisé comme une chaîne en C, mais ce n'est pas une chaîne. C'est un pointeur (ou parfois un tableau).

Il y a un operator+ (const std::string&, char) qui concatène, mais le compilateur ne le cherchera même pas, car le premier argument n'est pas un std :: string.

Une solution consiste donc à créer manuellement la chaîne:

string name = std::string("ab")+'c';

Le compilateur peut maintenant trouver le bon opérateur + appeler.

En C ++, le compilateur recherche une fonction avec ce prototype:

T operator+ (const char*, char);

Puisqu'il n'en existe pas, il ne peut pas comprendre ce que T est et ne peut pas résoudre l'appel operator<<. Il revient donc à la seule solution qui reste: l'ajout d'un pointeur. Comme dans la réponse de Josh, la caténation dans une chaîne ne pose aucun problème, car une fonction existe pour elle.

Étant donné le code C ++:

std::string name =  "ab"+'c';

L'équivalent en Java est:

String name = "ab".substring('c');

Les deux favorisent char à int. Bien sûr, en Java, la plage est vérifiée et génère donc une exception. En C ++, vous obtenez juste un comportement indéfini (ou une telle chose).

Java:

public class Main
{
    public static void main(String[] args)
    {
        System.out.println("AB" + 'c');
    }
}

La sortie est:

  

ABc

Modifier:

En réalité, le compilateur code la chaîne ABc ...

Si vous faites " AB " + argv [0] .charAt (0); pour le faire utiliser une variable, le compilateur le fait (essentiellement):

StringBuilder b = new StringBuilder;
b.append("AB");
b.append(argv[0].charAt(0));
System.out.println(b.toString());

Vous pouvez concaténer des chaînes et des caractères en C #. Ce n'est pas aussi strict que le C ++, je suppose.

Cela fonctionne très bien en C #:

string test = "foo" + 'b';

Un compilateur C ++ ne concatène pas automatiquement les littéraux chaîne avec les littéraux caractères. Mais il va concaténer les littéraux de chaîne les uns avec les autres. La syntaxe est la suivante:

const char * cs = "ab" "c"; // append string-literals

Comme d'autres l'ont mentionné, string n'est pas un type de langage C ++ intégré . Mais il existe un type <=> dans la bibliothèque standard C ++. Voici quelques exemples d'utilisation:

#include <string>
const char * cs = "ab" "c";
std::string s1( cs );
std::string s2( "ab" "c" );
std::string s3 = "ab" "c";

Eh bien, ce que je ferais habituellement en C ++ est

string name = string (" ab ") + 'c';

N'oubliez pas que le littéral " ab " n'est pas de type chaîne. Vous espériez qu'il n'y a pas de & Quot; + & Quot; cela fonctionne entre les tableaux de caractères et les caractères, et en espérant que le compilateur puisse remarquer que vous voulez vraiment que le résultat soit un std :: string, puis allez analyser votre expression à droite pour une combinaison de conversions implicites pouvant se combiner. avec le ou les opérateurs pour produire un résultat de ce type. Cela me semble être une tâche difficile.

Peu importe, peu importe. Vous voyez, en C, la seule différence entre un tableau et un pointeur est la façon dont leur mémoire est allouée. Une fois que vous en avez un, vous avez essentiellement un & "; Tableau / pointeur" & ";. Ainsi & Quot; + & Quot; est un opérateur défini sur tous les tableaux et tous les pointeurs, qui prend un autre argument de type entier, effectue un calcul mathématique du pointeur et renvoie un pointeur sur autant d'éléments situés au-delà de cet endroit. En outre, dans C & Quot; char & Quot; est vraiment juste un autre type de type entier. Ces décisions en matière de conception en C étaient à la fois des hacks utiles, mais comme cela arrive souvent avec des hacks, elles se combinent avec des résultats intuitivement inattendus. Donc, tout & Quot; ab & Quot; + 'c' fait pour vous est une adresse de 99 octets de retour où le " ab " littéral se trouve être stocké dans la mémoire.

Parfois, vous pouvez vous fier aux conversions implicites, mais vous devez vraiment être prêt à aider votre compilateur à sortir un peu plus tard.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top