2013-07-28 17 views
14

Jak wiem kompilacja C-podobne ciągi są przechowywane w pamięci statycznej jako tylko jedno wystąpienie. Na przykład dostałem zarówno true na przykładzie przykładu gcc 4.6 poniżej. Ale zastanawiam się, czy to zawsze prawda i może być przenośna. Zachowanie w C i C++ jest interesujące.Łańcuchy w statycznych instancjach pamięci liczyć

#include <iostream> 

bool amIportable(const char* value) { 
    const char* slocal = "Hello"; 
    return (slocal==value); 
} 

int main() { 
    const char* s = "Hello"; 
    std::cout << std::boolalpha 
      << amIportable(s) << '\n' 
      << amIportable("Hello") << '\n'; 
} 

Odpowiedz

12

Nie, to nie zawsze jest prawdą, ani nie jest przenośne.

Scalanie identycznych literałów łańcuchowych jest optymalizacją wykonywaną przez kompilator i linker pracujący razem. Najnowsze wersje zarówno GCC, jak i kompilatora Microsoftu, obsługują to, ale tylko wtedy, gdy ustawione są pewne przełączniki optymalizacji.

I to nie tylko funkcja "włączony" lub "wyłączony". Różne kompilatory i różne ustawienia optymalizacji mają również wpływ na to, w jaki sposób jest wykonywany. Na przykład, czasami literały łańcuchowe są łączone tylko w zakresie pojedynczej funkcji, innym razem na poziomie jednostki tłumaczeniowej, i jeszcze innym razem, gdy linker może zaangażować się w to w wielu jednostkach tłumaczeniowych.

Jest to dozwolone, ponieważ standardy C i C++ pozostawiają to zachowanie jako zależne od implementacji.

9

Nie, jego implementacja zależy zarówno od C, jak i C++.

C11 §6.4.5/7 łańcucha znaków

jest określone czy Tablice te są odrębne warunkiem, że ich elementy mają odpowiednie wartości. Jeśli program próbuje zmodyfikować taką tablicę, zachowanie jest niezdefiniowane.

C++ 11 §2.14.5/12 łańcucha znaków

czy wszystkie literałami łańcuchowe są odrębne (to jest, są przechowywane w obiektach zachodzących na siebie), jest zastosowanie zdefiniowane. Efekt próby modyfikacji literału łańcuchowego jest niezdefiniowany.

2

Ale zastanawiam się, czy to zawsze prawdziwe

No, przynajmniej średnia C mówi coś w stylu „czy dwa identyczne literały ciągów znaków są przechowywane w tej samej tablicy jest realizacja zdefiniowana”.

2

Porównujesz dwa różne ciągi literowe, które mają wartość mają tę samą wartość. Zgodnie ze standardem C++ zdefiniowano implementację , czy identyczne ciągi literowe zajmują w tej samej pamięci, czy nie (co oznacza, że ​​implementacja musi udokumentować, co robi); zgodnie ze standardem C, jest to nieokreślony. (Przypuszczam, że standard C++ pozwoliłby implementacji udokumentować coś na wzór "string literały identycznej treści współużytkują to samo wystąpienie, jeśli są w tej samej jednostce tłumaczeniowej i nie dzielą tego samego instancji w inny sposób.)

Jeśli twoim celem jest, aby móc po prostu porównać wskaźniki, zwykle rozwiązaniem jest użycie funkcji (statyczny, czy jest członkiem klasy) która zwraca ciąg dosłowne:

char const* 
value() 
{ 
    return "Hello"; 
} 

bool 
isHello(char const* str) 
{ 
    return str == valule; 
} 

i następnie upewnij się, że wszystkie wystąpienia ciągu są uzyskiwane przez dzwoniąc pod numer value().