Quelle est la différence entre char a[] = ?chaîne?; et char *p = ?chaîne?;?
Comme le titre le dit, Quelle est la différence entre
char a[] = ?string?; and
char *p = ?string?;
Cette question a été posée à moi en interview.
J'ai même pas de comprendre l'énoncé.
char a[] = ?string?
Ici ce qui est ?
opérateur? Est-ce une partie d'une chaîne ou il a une certaine signification particulière?
- Ne compile pas sur MSVC...
- Le pari de l'interviewer signifiait " au lieu de ?. L' ? le symbole est utilisé pour le tertiaire de l'opérateur, mais ce n'est pas la bonne syntaxe pour elle.
- C'est probablement un cas de mojibake. Ce n'est pas du C++.
- Certainement n'est pas de compilateur sur C ou C++ compilateur.
return blah ? doFoo() : doOtherFoo();
est un exemple de l' ? de l'opérateur. Il est fonctionnellement équivalent àif (blah) return doFoo(); else return doOtherFoo();
.- Il est possible que la question a été à l'aide de la début/fin de citations et de la police pour une raison quelconque ne pouvait pas trouver, donc rendu comme
?
s. - Ma conjecture: le Code a été copié dans MS Word, des devis ont été convertis, et puis en quelque sorte de nouveau converti. Ou il manque une
#define ? "
. Ne sais pas si ça compile, mais. - difference-between-char-str-string-and-char-str-string
- la question a été modifié (les points d'interrogation ont été remplacés par des guillemets doubles, le cas échéant) afin d'améliorer la visibilité sur Google et il a été explicitement demandé de ne pas reculer. Pourquoi avez-vous fait? Totalement imprudent de se déplacer.
- La question a été modifié au point d'être unintelligble! J'ai eu à lire la question d'origine à même de comprendre ce qui était demandé.
- Plus précisément, les points d'interrogation ont été une partie de l'OP question, donc le retrait de ces faits, il est impossible de comprendre ce qui était demandé.
Vous devez vous connecter pour publier un commentaire.
La première est la matrice de l'autre pointeur.
Source: comp.lang.c liste des questions-réponses · Question 6.2
const char *p = "string"; p = "another string"; printf("%c", p[3]);
(Oui,char *p = "string";
sera une erreur de compilation)La
?
semble être une faute de frappe, il n'est pas sémantiquement valide. Donc la réponse suppose la?
est une faute de frappe et ce qui explique probablement l'interviewer en fait destiné à le demander.Les deux sont très différents, pour commencer:
Lire sur pour des explications plus détaillées:
Le Tableau version:
Crée un tableau qui est assez grand pour contenir la chaîne de caractères littérale de "chaîne", y compris ses
NULL
terminator. Le tableaustring
est initialisé avec le littéral de chaîne "string". Le tableau peut être modifié à une date ultérieure. Aussi, la taille du tableau est connu, même au moment de la compilation,sizeof
opérateur peut être utilisé pour déterminer sa taille.Le pointeur de la version:
Crée un pointeur sur une chaîne littérale "chaîne". C'est plus rapide que la matrice de version, mais la chaîne de caractères pointée par le pointeur ne doit pas être modifié, car il est situé dans une lecture que définis par l'implémentation de la mémoire. La modification d'une chaîne de caractères littérale résultats dans Comportement Indéfini.
En fait C++03 dénonçait[Ref 1] utilisation de la chaîne de caractères littérale sans
const
mot-clé. Ainsi, la déclaration doit être:Aussi,vous besoin d'utiliser le
strlen()
fonction, et passizeof
pour trouver la taille de la chaîne depuis lesizeof
opérateur va vous donner la taille du pointeur de variable.Quelle version est mieux et lequel dois-je utiliser?
Dépend de l'Usage.
Remarque: C'est un pas de C++, mais c'est C spécifique.
Noter que, l'utilisation de la chaîne de caractères littérale sans
const
mot-clé est parfaitement valide en C.Toutefois, la modification d'un littéral de chaîne est encore un Comportement Indéfini en C[Ref 2].
Cela soulève une question intéressante,
Quelle est la différence entre char* et const char* lorsqu'il est utilisé avec des littéraux de chaîne en C?
Pour Standerdese Fans:
[Ref 1]C++03 Standard: §4.2/2
C++11 supprime simplement la citation ci-dessus, ce qui implique qu'il est illégal de code en C++11.
[Ref 2]standard C99 6.4.5/5 "Littéraux de Chaîne - Sémantique":
If you do not need to make any changes to the string, use the pointer version.
- si vous n'avez pas besoin de faire des changements à la chaîne, vous voudrez probablement utiliserconst char a[] = "string";
, c'est à dire juste ajouter unconst
. Elle permet d'éviter la réinstallation, lorsque l'éditeur de liens dynamique fait son travail pendant le démarrage (sur Linux, au moins). Voir Comment écrire des bibliothèques partagées la section 2.4.1 pour une plus longue discussion.Ce alloue de la chaîne sur la pile.
Cela crée un pointeur sur la pile qui pointe vers le littéral dans le segment de données du processus.
?
est celui qui l'a écrit ne sachant pas ce qu'ils faisaient.char a[]
... alloue...sur la pile" suppose qu'il y a à l'intérieur d'une fonction et pas global, et se réfère davantage à l'a[]
tout en ne mentionnant que l'intérieur d'une fonction il y a en fait une copie de l'intégralité du texte de la constante de segment de données de la pile.char*
utilisation qui crée un non-const
pointeur sur la pile ou mondial dans le segment de données et initialise lors de l'exécution ou de (probablement) au moment de la compilation, respectivement, à l'adresse de la const texte.const
qualificatif est déprécié en C++03, de Sorte que le deuxième extrait n'est pas légal de code C++.Pile, tas, datasegment(et BSS) et un segment de texte sont les quatre segments de la mémoire des processus. Toutes les variables locales définies seront dans la pile. Dynmically mémoire allouée à l'aide de
malloc
etcalloc
sera dans le tas. L'ensemble de ces et variables statiques seront dans le segment de données. Segment de texte aura le code assembleur du programme et certaines constantes.Dans ces 4 segements, segment de texte est le
READ ONLY
segment et dans l'ensemble des trois autres est pourREAD
etWRITE
.char a[] = "string";
- Cette proclamation va allouer de la mémoire pour les 7 octets dans la pile(car la variable locale) et elle permet de conserver tous les 6 caractères(s, t, r, i, n, g
) plus le caractère NULL (\0
) à la fin.char *p = "string";
- Cette déclaration va allouer de la mémoire pour les 4 octets(si il est en 32 bits machine) dans la pile(parce que c'est aussi une variable locale) et maintenez le pointeur de la chaîne constante dont la valeur est"string"
. Ce 6 octet de la chaîne constante sera dans le segment de texte. C'est une valeur constante. Pointeur de variablep
juste points de cette chaîne.Maintenant
a[0]
(indice de 0 à 5) est-à-dire l'accès premier caractère de cette chaîne qui est dans la pile. Donc, nous pouvons faire écrire également à cette position.a[0] = 'x'
. Cette opération est autorisée, car nous avonsREAD WRITE
l'accès à la pile.Mais
p[0] = 'x'
sera conduit à l'accident, parce que nous avons seulementREAD
l'accès à un segment de texte. Erreur de Segmentation se fera si nous ne tout écrire sur le segment de texte.Mais vous pouvez changer la valeur de la variable
p
, parce que ses variables locales dans la pile. comme ci-dessousCela est autorisé. Ici, nous sommes à la modification de l'adresse stockée dans la variable d'indicateur
p
à l'adresse de la chaînestart
(nouveaustart
est aussi un lire uniquement les données dans un segment de texte). Si vous souhaitez modifier les valeurs présentes dans*p
les moyens allez-mémoire allouée dynamiquement.Maintenant
p[0] = 'x'
opération est autorisée, parce que maintenant nous avons écrit dans le tas.char *p = "string";
crée un pointeur vers la mémoire où la chaîne de caractères littérale"string"
est stocké. En essayant de modifier la chaine quep
points à conduit à un comportement indéterminé.char a[] = "string";
crée et initialise un tableau de son contenu, par l'aide de la chaîne littérale"string"
.Ils diffèrent quant à l'endroit où la mémoire est stockée. Idéalement, le second doit utiliser const char *.
La première
crée automatiquement un tampon assez grand pour contenir les caractères et les copies (y compris le terminateur null).
La seconde
doit utiliser const et crée simplement un pointeur qui pointe à la mémoire stockée dans des statique de l'espace où il est illégal de le modifier.
L'inverse (du fait, vous pouvez modifier le premier en toute sécurité et de ne pas la deuxième), c'est qu'il est sûr de retourner le deuxième pointeur de fonction, mais pas la première. C'est parce que la deuxième restera valide pointeur de la mémoire en dehors de la portée de la fonction, la première ne sera pas.
a
déclare un tableau dechar
valeurs -- un tableau dechar
s qui se termine.p
déclare un pointeur, qui se réfère à une immuable, résilié, chaîne C, dont l'exact emplacement de stockage est mise en œuvre définies. Notez que cela devrait êtreconst
-qualifiés (par exemple,const char *p = "string";
).Si vous l'imprimer à l'aide de
std::cout << "a: " << sizeof(a) << "\np: " << sizeof(p) << std::endl;
, vous verrez les différences de leurs tailles (remarque: les valeurs peuvent varier en fonction du système):Je suppose qu'ils ont été une fois guillemets
"string"
, qui potentiellement ont été convertis en "guillemets", ne pouvait pas être représentée en tant que telle, le long de la voie, et ont été convertis en?
.char
tampon).char
tampon, alors il devrait être un[static] const char a[] = "xyz";
, pasconst char* p = "xyz";
niconst char* const p = "xyz";
- l'ancien implique p peut être déplacée au point d'ailleurs, et si ce n'est pas prévu alors il est préférable de ne pas laisser la possibilité, et à la fois demander au compilateur de l'espace pour le pointeur de texte et à mon humble avis - montre juste un manque de précision du modèle mental de ce qui est demandé de le compilateur, et les déchets de l'espace et du temps dans un unoptimised construire.[static] const char[]
résultats dans "le gaspillage d'espace et de temps".Le C et le C++ sont très similaires Pointeur vers Tableau des relations...
Je ne peux pas parler pour l'exacte des emplacements de mémoire des deux déclarations que vous posez sur, mais j'ai trouvé qu'ils articles intéressants et utiles pour la compréhension de certaines différences entre la déclaration de Pointeur de char, et un char déclaration de Tableau.
Pour plus de clarté:
C Pointeur et un Tableau de la relation
C++ Pointeur vers un Tableau
Je pense qu'il est important de se rappeler qu'un tableau, dans le C et le C++, est un pointeur constant pour le premier élément du tableau. Et, par conséquent, vous pouvez effectuer l'arithmétique des pointeurs sur le tableau.
char *p = "chaîne de caractères"; <--- C'est un pointeur qui pointe vers la première adresse d'une chaîne de caractères.
la suite est également possible:
À ce point p maintenant référence à la première adresse de la mémoire de l'un (l'adresse du premier élément)
et ainsi de *p == 's'
*(p++) == 't' et ainsi de suite. (ou *(p+1) == 't')
et la même chose pourrait fonctionner pour un: *(a++) ou *(un+1) serait également l'égalité de 't'