Diferența dintre char* și char[] (Programare, C++)

Nemo a intrebat.

Știu că este o întrebare foarte simplă. Sunt confuz în ceea ce privește de ce și cum sunt diferite următoarele.

char str[] = "Test";
char *str = "Test";

Comentarii

  • Răspunsurile de mai jos explică destul de mult, dar o diferență suplimentară este că varianta array vă oferă o modalitate convenabilă de a lua dimensiunea șirului inițial (inclusiv terminatorul nul) – sizeof(str). –  > Por davmac.
  • Vezi și: stackoverflow.com/q/1287306/365102 –  > Por Mateen Ulhaq.
  • Sfatul meu obișnuit: citiți secțiunea 6 din comp.lang.c FAQ. –  > Por Keith Thompson.
  • Ar trebui ca acest lucru să facă parte din [c++-faq]? –  > Por Mateen Ulhaq.
  • …Vezi și răspunsul meu la o întrebare similară: stackoverflow.com/questions/6823249/c-pointer-question/… –  > Por Mateen Ulhaq.
7 răspunsuri
K-ballo
char str[] = "Test";

Este o matrice de chars, inițializat cu conținutul din „Test”, în timp ce

char *str = "Test";

este un pointer la șirul literal (const) „Test”.

Principala diferență între ele este că primul este un array, iar celălalt este un pointer. Array-ul deține conținutul său, care se întâmplă să fie o copie a lui "Test", în timp ce pointerul se referă pur și simplu la conținutul șirului (care, în acest caz, este imuabil).

Comentarii

  • De ce este char* str este utilizat în mod obișnuit atunci când str denotă un șir de caractere. Nu este str[] mai bine? –  > Por Nemo.
  • @Ajan: str[] este o matrice dimensionată static, care copiază șirul. Dacă ai nevoie de o copie -necesară doar dacă ai pretenția de a modifica șirul-, atunci matricea este mai bună. În caz contrar, este preferabil un pointer la un șir literal. –  > Por K-ballo.
  • @Ajan: Ambele nu denotă constante, șirurile literale sunt permise să se lege la pointeri non const doar pentru a sprijini C-ul tradițional. –  > Por K-ballo.
  • Bine, asta explică de ce primesc warning: deprecated conversion from string constant to ‘char*’ –  > Por Nemo.
  • @K-ballo dacă str este un pointer în char *str = "Test"; atunci înseamnă că literalul „Test” este stocat undeva în memorie? –  > Por ajaysinghnegi.
rnrneverdies

Diferența constă în memoria STACK utilizată.

De exemplu, atunci când se programează pentru microcontrolere, unde se alocă foarte puțină memorie pentru stivă, face o mare diferență.

char a[] = "string"; // the compiler puts {'s','t','r','i','n','g', 0} onto STACK 

char *a = "string"; // the compiler puts just the pointer onto STACK 
                    // and {'s','t','r','i','n','g',0} in static memory area.

Comentarii

  • Se aplică doar pentru microcontrolere? Dacă nu, atunci care este diferența dintre zona de memorie statică și stivă? –  > Por ajaysinghnegi.
Luka Rahne

Unul este pointer și unul este matrice. Ele sunt tipuri diferite de date.

int main ()
{
   char str1[] = "Test";
   char *str2 = "Test";
   cout << "sizeof array " << sizeof(str1) << endl;
   cout << "sizeof pointer " << sizeof(str2) << endl;
}

ieșire

sizeof array 5
sizeof pointer 4

Comentarii

  • asta este ceva nou, deci când este stocat în pointer care nu trebuie să fie terminat de caracterul NULL? –  > Por user3995169.
  • @Stack Overflow ponterul este stocat ca o adresă care ocupă 4 octeți. Un șir mai lung ar fi returnat ca sizeof array 20 sizeof pointer 4 –  > Por Luka Rahne.
Jon Reid

Un pointer poate fi redirecționat către altceva:

char foo[] = "foo";
char bar[] = "bar";

char *str = foo;  // str points to 'f'
str = bar;        // Now str points to 'b'
++str;            // Now str points to 'a'

Ultimul exemplu de incrementare a pointerului arată că puteți itera cu ușurință peste conținutul unui șir, element cu element.

Peter Olson

Primul

char str[] = "Test";

este o matrice de cinci caractere, inițializată cu valoarea "Test" plus terminatorul nul ''.

Al doilea

char *str = "Test";

este un pointer la locația de memorie a șirului literal "Test".

Comentarii

  • Nu sunt sigur, dar este o matrice de 5 caractere. {'T', 'e', 's', 't', ''}. –  > Por Bill Lynch.
  • @PeterOlson ați spus pointer la locația de memorie. Asta înseamnă că ptr stochează adresa de pornire a „Testului”? Un lucru pe care îl știu în mod clar este că pointerii pot stoca doar adrese, iar „Test” nu este o adresă. –  > Por user3995169.
  • @StackOverflow Da, un pointer indică adresa de pornire, iar apoi puteți găsi șirul de caractere mergând la adresa de pornire (indicând litera T) și mergând spre dreapta până când se ajunge la terminatorul nul. –  > Por Peter Olson.
  • @PeterOlson Înseamnă că literalul „Test” este stocat undeva în memorie și este terminat de ‘’ și ptr care indică ‘T’ din „Test”? Dacă da, în ce memorie se află „Test”? –  > Por ajaysinghnegi.
Matthieu Brucher

Începând cu C++11, cea de-a doua expresie este acum invalidă și trebuie scrisă:

const char *str = "Test";

Secțiunea relevantă din standard este apendicele C, secțiunea 1.1:

Modificare: String literals made const

Tipul unui literal de șir de caractere se modifică din „array of char” în „array of const char”. Tipul unui literal de șir de caractere char16_t se modifică de la „array of some-integer-type” la „array of const char16_t”. Tipul unui literal de șir char32_t se modifică de la „array of some-integer-type” la „array of const char32_t”. Tipul unui literal de șir larg se modifică de la „array of wchar_t” la „array of const wchar_t”.

Justificare: Se evită astfel apelarea unei funcții supraîncărcate necorespunzătoare, care s-ar putea aștepta să își poată modifica argumentul.

Efectul asupra funcției originale: Modificarea semanticii unei funcții bine definite.

Comentarii

  • Să presupunem că char* este tipul de retur al unei funcții char* fun()? Va exista vreo schimbare în specificația tipului de returnare sau a valorii returnate acum? –  > Por ajaysinghnegi.
  • @AjaySinghNegi Categoric. Trebuie să returnați un const char*. –  > Por Matthieu Brucher.
Tim

"Test" este o matrice de cinci caractere (4 litere, plus terminatorul nul).

char str1[] = "Test"; creează acest array de 5 caractere și îl numește str1. Puteți să modificați conținutul acestui tablou cât doriți, de ex. str1[0] = 'B';

char *str2 = "Test"; creează acel array de 5 caractere, nu îi dă un nume și creează, de asemenea, un pointer numit str2. Se setează str2 pentru a indica acel array de 5 caractere. Puteți urmări pointerul pentru a modifica matricea cât doriți, de exemplu str2[0] = 'B'; sau *str2 = 'B';. Puteți chiar să realocați acest pointer pentru a indica altundeva, de exemplu str2 = "other";.

O matrice este textul între ghilimele. Pointerul nu face decât să îl indice. Puteți face multe lucruri similare cu fiecare dintre ele, dar sunt diferite:

char str_arr[] = "Test";
char *strp = "Test";

// modify
str_arr[0] = 'B'; // ok, str_arr is now "Best"
strp[0] = 'W';    // ok, strp now points at "West"
*strp = 'L';      // ok, strp now points at "Lest"

// point to another string
char another[] = "another string";
str_arr = another;  // compilation error.  you cannot reassign an array
strp = another;     // ok, strp now points at "another string"

// size
std::cout << sizeof(str_arr) << '
';  // prints 5, because str_arr is five bytes
std::cout << sizeof(strp) << '
';     // prints 4, because strp is a pointer

pentru ultima parte, rețineți că sizeof(strp) va varia în funcție de arhitectură. Pe o mașină pe 32 de biți, va fi de 4 octeți, pe o mașină pe 64 de biți va fi de 8 octeți.

Comentarii

  • Nu puteți modifica literalele de șiruri de caractere, acestea sunt imuabile; a face acest lucru este un comportament nedefinit. –  > Por K-ballo.
  • strp[0] = 'W'; invocă un comportament nedefinit, deoarece încearcă să modifice un șir constant. –  > Por davmac.
  • în array-uri putem modifica conținutul, dar nu și în cazul pointerilor. Vă rugăm să vă corectați răspunsul, este greșit. Cineva ar putea învăța ceva greșit citind acest răspuns @Tim –  > Por user3995169.

Tags: