12
votes

Comment stocker un const Char * à un char *?

J'ai Ce code qui fonctionne comme prévu: xxx

si je "D Aimez stocker le résultat à un char * (car certaines fonctions dans un cadre que j'utilise utilise uniquement char * comme entrée) sans utiliser le Strcpy (pour la praticité et la lisibilité du code, et apprendre aussi), comment pourrais-je faire? Garder dans const , cela fonctionne bien: xxx

mais j'ai toujours const .

essayer de simplement utiliser char * : xxx

i obtenir conversion invalide de "const char *" à 'Char *' . Quelle est la meilleure habitude pour ce type de conversion?


1 commentaires

Que veux-tu faire? Si vous ne voulez pas changer la chaîne, le premier idiome vous sert et n'utilise pas de mémoire supplémentaire; Si vous souhaitez modifier la chaîne, vous devez copier son contenu ailleurs (vous avez donc besoin de Strcpy ou similaire).


4 Réponses :


-1
votes

en C ++, la manière typique de "goutte const " est en utilisant const_cast <> : xxx

ceci est, de cours, fronça les sourcils, laids, moche et potentiellement dangereux, car il est vraiment possible que getname () renvoie un pointeur sur quelque chose que ne devrait pas être changé , puis vous allez donner vous-même la permission de le changer. C'est un bon moyen de devenir très difficile de trouver des bugs, dans ce cas.

Une solution de contournement consiste à utiliser un std :: string comme zone de détention temporaire; Il signifiera la copie de la chaîne mais qui pourrait être acceptable de performance-wise: xxx

ce ne sera bien sûr bien sûr que si nom n'est pas conservé Lorsque s est hors de portée. Si tel est le cas, vous allez avoir une forme de couche de stockage de chaîne persistante.


6 commentaires

Retirer Const d'un Const Const * comportement non défini?


Si je peux demander, pourquoi suggérez-vous quelque chose qui est froncé sur, sans donner d'autres suggestions?


@Default Parce que c'était ce que l'affiche voulait savoir comment faire, et je ne saurais savoir pour certains que ce soit mauvais dans la situation en question.


.c_str () est const. Char * Nom = s.c_str (); n'est pas compilable.


@Default Supprimer const n'est pas UB. Mais vous êtes correct que std :: string :: c_str ne fonctionne pas car il retourne const char * .


Attention à modifier les caractères dans un littéral de chaîne C ++ est UB. Ils sont généralement stockés dans une section de mémoire en lecture seule. Casting Le const ne provoquera pas le problème, mais une tentative ultérieure d'écrire dans cette région de mémoire sera. Ne suggère pas de telles choses; Le seul moyen de créer correctement une chaîne mutable d'un littéral de chaîne C ++ est de le copier.



9
votes

renvoyer "Texte de test"; code> renvoie un pointeur sur un lecture seule em> string littéral em>.

Si vous utilisez un fonction qui prend un char * code> en entrée et que vous avez un const char * code> (tel qu'un littéral en lecture seule), vous devez fournir une copie profonde de la chaîne à partir de ce const char * code> à ces fonctions. p>

sinon, vous risquez un comportement non défini à l'exécution si une fonction tente de modifier une chaîne en lecture seule. P>

Ce que vous avez actuellement est adéquat; En supposant que vous ne puissiez pas travailler avec std :: string code>. (Si vous peut em> fonctionner avec std :: string code> et em> toutes vos fonctions-structures prennent un const char * code> entrée, Ensuite, je vous suggère de refactoriser votre code pour utiliser un std :: string code> et transmettez la sortie de la méthode C_STR () CODE> sur cette classe de chaîne à vos fonctions-cadre. ) p>

Enfin, si certaines fonctionnalités de cadre nécessitent un char * code>, vous pouvez toujours vous construire une petite classe d'adaptateur: P>

class Adapter
{
public:
    Adapter(const& Adapter) = delete; /*don't try to copy me please*/
    Adapter& operator=(const Adapter& ) = delete; /*don't try to copy me please*/
    Adapter(const char* s) : m_s(::strdup(s))
    {
    }
    ~Adapter() /*free memory on destruction*/
    {
        ::free(m_s); /*use free to release strdup memory*/
    }
    operator char*() /*implicit cast to char* */
    {
        return m_s;
    }
private:
    char* m_s;
};


12 commentaires

Et si je veux "copier" le contenu const char * sur un char * (donc, sans spécifier la taille fixe)? Je ne connais pas la taille de ce char *, depuis plus tard, je vais concatez d'autres caractères.


Oh, attendez. Je vois que je peux utiliser char * nom; et que strcpy (nom, getname ()); aussi. Fondamentalement, j'ai eu une chaîne non longueur-définie qui servira ma tâche. Est-ce que c'est correct?


@Paizza Non. Utilisez quelque chose comme std :: String Name = getName (); puis passe nom.c_str () à n'importe quelle fonction de cadre qui attend un const * .


Il y a aussi STRDUP pour créer une copie d'une chaîne. Vous aurez besoin de libérer la mémoire plus tard, cependant, il est donc beaucoup plus facile d'utiliser std :: string en C ++.


Vous devez écrire nom.c_str () . c_str est une fonction .


chaîne est bon, mais j'ai besoin de char * plus tard, pas const char * :(. c_str () retour Const. Je pense que je ne peux pas passer un chaîne à un char * non?


Par intérêt, pourquoi avez-vous besoin d'un Char * plus tard?


Le seul moyen est de définir une taille fixe (deviner suffisamment) et utilisez Strcpy. C'est risqué, je peux avoir une violation de la mémoire d'accès si le char * a grandi plus que la taille que j'ai définie :(


@Bathsheba: Comme je l'ai dit, la fonction utilisée par le cadre Taks Char * en entrée, je ne peux pas les changer!


@pazza dans votre question, vous dites certaines fonctions dans un cadre que j'utilise utilisez const char * comme entrée


@ user2079303: Je me trompe, désolé! J'ai mis à jour la question. J'ai besoin de char *


D'ACCORD; Pensez à utiliser quelque chose sur les lignes de la classe que je donne dans la réponse.



15
votes

La meilleure habitude de ce type de conversion consiste à utiliser std :: chaîne tout au long de votre code. Étant donné que le cadre que vous utilisez prend const char * comme entrée, vous pouvez toujours le transmettre les résultats de c_str () Appelez sur votre std :: string : xxx

Un deuxième meilleur utilise const char * dans votre code: xxx

puisque le cadre que vous utilisez prend const char * vous sont bons ici aussi.

Si vous avez besoin d'un pointeur non constitué, il n'y a aucun moyen de copier la chaîne. Vous pouvez faire une fonction qui le fait pour vous, mais vous resterez responsable de libérer les copies que vous en obtenez: xxx


0 commentaires

-2
votes

Vous pouvez explicitement le jeter. (char *) getname () code>. Mais vous ne devriez probablement pas. Parce que le bit const code> signifie quelque chose comme "promettez de ne pas le changer". Donc, si j'ai une fonction Void FOO (Const Char * String) Code> Je suis Saiing: "Donnez-moi un pointeur à une chaîne. Je ne le changerai pas." Et si vous déclarez une variable const char * string = "bonjour"; code> vous dites, cette chaîne ne doit pas être modifiée. Et parce que vous faites cette promesse, le compilateur sait et peut rendre votre code plus efficace. C'est pourquoi:

const char* a = "hello";
const char* b = "hello";
(a==b); //is probably true


1 commentaires

Pourquoi suggérez-vous des moulages potentiellement dangereux? Le seul moyen correct d'obtenir une chaîne non-Const C à partir d'un littéral de chaîne C ++ est de le copier. Toute tentative de modification de la version non créée non-const est UB. S'il vous plaît ne proposez pas une méthode qui permettra (presque certainement) entraînera le diagnostic de comportement du programme sur la ligne.