Równoważność wskaźnika i typu string

Równoważność wskaźnika i typu string
Wazka260196
  • Rejestracja: dni
  • Ostatnio: dni
  • Lokalizacja: Kraków
  • Postów: 52
0

Witam wszystkich!

Otóż w poradniku o pointerach Gynvaela Coldwinda (dokładniej odcinek nr 8.) spotkałem się z funkcją która wyglądała mniej-więcej w ten sposób :

Kopiuj
 const char *type_to_str(DWORD t)
{
	switch(s)
	{
		case MEM_COMMIT: return "MEM_COMMIT";
		case MEM_MAPPED: return "MEM_MAPPED";
		case MEM_PRIVATE: return "MEM_PRIVATE";
	} 
}

Chciałbym się upewnić czy mój tok rozumowania zwracanej w tym przypadku wartości jest poprawny.

Generalnie wydaje mi się, że string jest pewną tablicą char-ów, która zakończona jest null-bytem (i wygląda to tak zarówno w C jak i C++ - czy mam rację?). Funkcja ta zwraca mi wskaźnik na pewną stałą typu char. Jednak w returnie jakiś string. Mam rozumieć że w tym przypadku funkcja de facto zwróciła mi wskaźnik na pierwszy element anonimowej tablicy, która zawiera odpowiedni ciąg znaków (np. "MEM_COMMIT" itp.). Czy ten tok rozumowania jest poprawny? Czy w C++ przekazanie stringa jako parametru funkcji w ten sposób: foo("bar") przekazuje tak na prawdę wskaźnik na pierwszy element tablicy o nieznanej mi nazwie która zawiera w sobie ciąg "bar"? Czy każdy string można tak traktować?

KU
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 21
0
Wazka260196 napisał(a):

Czy w C++ przekazanie stringa jako parametru funkcji w ten sposób: foo("bar") przekazuje tak na prawdę wskaźnik na pierwszy element tablicy o nieznanej mi nazwie która zawiera w sobie ciąg "bar"??

Zalezy od definicji foo(). Jesli bedzie to void foo(const char*) to kopiujesz wskaznik, a jesli void foo(std::string) to string zostanie skopiowany w calosci.

fasadin
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 4883
3

nie masz racji ale ja masz

masz std::string z c++ i masz c-string z C to sa dwie rozne rzezcy. Np string ma taka funkcje jak c_str() ktora przeksztalca stringa na cstringa
W returnie nie jest string a cstring ;)
poszukaj roznice miedzy cstringiem a stringiem w googlach

jezeli w c++ masz jako parametr string a przekazujesz ("text") to zostanie on po prostu przekonwertowany (rzutowany) na stringa (w duzym uproszczeniu...)

Ogolna idee masz dobra. Ale detale masz zle ;)

Wazka260196
  • Rejestracja: dni
  • Ostatnio: dni
  • Lokalizacja: Kraków
  • Postów: 52
0

Ok zagalopowałem się i zamiast pomyśleć napisałem posta :)

A co z pierwszą częścią pytania? Tj. o to co tak na prawdę zwraca return? Dodam, że kod był pisany zgodnie z kanonami języka C. Wiem, że w C++ mogę po prostu zwrócić string i po problemie ale co dokładnie dzieje się w zamieszczonym przeze mnie przykładzie?

twonek
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 2500
1
Wazka260196 napisał(a):

string jest pewną tablicą char-ów, która zakończona jest null-bytem
std::string jest klasą, której implementacja jest zależna od kompilatora: http://stackoverflow.com/questions/1466073/how-is-stdstring-implemented.
Przy czym od C++11 implementacje oparte na reference counting już nie są zgodne ze standardem.
C-string jest tablicą znaków zakończoną nullem.

(i wygląda to tak zarówno w C jak i C++ - czy mam rację?)
Tak jeśli mówimy o c-stringach. W C nie ma std::string.

Mam rozumieć że w tym przypadku funkcja de facto zwróciła mi wskaźnik na pierwszy element anonimowej tablicy, która zawiera odpowiedni ciąg znaków (np. "MEM_COMMIT" itp.)
Ogólnie tak.

Gynvael Coldwind
  • Rejestracja: dni
  • Ostatnio: dni
  • Lokalizacja: Zurich, Switzerland
  • Postów: 457
3

Hmm w sumie już prawie wszystko zostało wytłumaczone, ale skoro zostałem wywołany do tablicy to coś napiszę.

Generalnie "asdf" w C/C++ to tzw. string literal (konkretniej w C++11 to jest ordinary string literal). Zgodnie z definicją w standardzie taki literal ma trzy ciekawe dla nas cechy:

  1. Jest lvalue (locator value), czyli de facto określa jakiś obiekt który jest "gdzieś" w pamięci.
  2. Ma static storage duration, to znaczy, że standard gwarantuje, że w dowolnym momencie działania programu ten obiekt jest w pamięci (identycznie jak zmienne globalne czy statyczne).
  3. Jest typu "array of char" (w C i chyba w starszych C++ też) lub "array of const char" (w nowszych standardach C++).

Oczywiście typ który zwraca funkcja to "pointer to a const char", natomiast ja sobie w kodzie robie bezczelnie "return array of const char".
Zezwala na to mechanizm, który nazywa się array-to-pointer conversion, który mówi w zasadzie to co napisaliście wyżej, czyli:

An lvalue or rvalue of type “array of N T” or “array of unknown bound of T” can be converted to a prvalue
of type “pointer to T”. The result is a pointer to the first element of the array.

Czyli:

Kopiuj
 return "asdf";

da identyczny efekt jak:

Kopiuj
 return &"asdf"[0];

Przy czym wspomnę od razu, że o ile zwracanie adresu string literal jest legalne, to zwracanie adresu lokalnej tablicy charów jest ofc bardzo złym pomysłem. Anty-przykład:

Kopiuj
const char *func() {
  char a[] = "asdf";
  return a;
}

(chodzi o to, że obiekt "a" przestaje istnieć od razu po wyjściu z funkcji i dostęp do niego wg standardu jest "undefined")

Generalnie wydaje mi się, że string jest pewną tablicą char-ów, która zakończona jest null-bytem (i wygląda to tak zarówno w C jak i C++ - czy mam rację?).

Tak, dokładnie. Przy czym na "string jako stała w kodzie" zazwyczaj mówi się ładnie "string literal" (żeby konkretnie doprecyzować, że chodzi o string zdefiniowany w kodzie, a nie o zmienną typu string; przy czym nie mam pojęcia jak po polsku jest "literal" - może "literał?" anyone?).
No i jak zostało napisane wyżej, trzeba uważać, żeby nie mylić "stringu w rozumieniu C" (zwanego, co było też wyżej powiedziane, c-stringiem) z klasą std::string w C++.

EDIT: A btw, wygląd na to że milion lat temu na 4p wrzuciłem jakiś losowy post o traktowaniu string literałów jako tablicy - Kruczki i sztuczki C cz. 1 (gdzieś tak w połowie).

Wazka260196
  • Rejestracja: dni
  • Ostatnio: dni
  • Lokalizacja: Kraków
  • Postów: 52
0

Hmmm...
Dzięki takim ludziom jak Wy dużo rzeczy się rozjaśniło. W takim razie std::string mogę poniekąd traktować w bardzo dużym przybliżeniu jako vector<char>? Wiem że tak naprawdę jest to:

Kopiuj
typedef basic_string<char> string

Jeżeli tak to jest to wszystko co chciałem się dowiedzieć.

kaczus
  • Rejestracja: dni
  • Ostatnio: dni
  • Lokalizacja: Łódź
  • Postów: 1403
2
Wazka260196 napisał(a):

Hmmm...
Dzięki takim ludziom jak Wy dużo rzeczy się rozjaśniło. W takim razie std::string mogę poniekąd traktować w bardzo dużym przybliżeniu jako vector<char>? Wiem że tak naprawdę jest to:

Kopiuj
typedef basic_string<char> string

Jeżeli tak to jest to wszystko co chciałem się dowiedzieć.

No nie do końca, wewnętrzna implementacja stringu nie musi być taka, by zawsze trzymać dane w ciągłej przestrzeni... stąd metoda c_str()....

Zarejestruj się i dołącz do największej społeczności programistów w Polsce.

Otrzymaj wsparcie, dziel się wiedzą i rozwijaj swoje umiejętności z najlepszymi.