Porównanie stringów po adresach

0

Cześć, w jednym programie znalazłem coś niepokojącego. Wychodzi na to, że stringi są porównywane po adresach.
Wygląda to mniej więcej tak, że najpierw są definiowane stałe stringi:


const string START;
const string STR_1;
const string STR_2;
//...i tak dalej
const string END;

A następnie są one porównywane mniej więcej w taki sposób:


const string * str = &STR_1;

if((str > &START) && (str < &END))
{

}

To jest nieco bardziej zaowaluowane (makra itd), ale właśnie rozwija się wszystko do postaci jak wyżej. Czy coś takiego ma prawo zadziałać? Wiem, że nie powinno się w taki sposób porównywać adresów, ale pisali to ludzie mądrzejsi niż ja i może są jakieś kruczki z tymi stałymi?

0

zalezy od budowy stringa, ale mi sie wydaje, ze porywnywanie adresow to jest bardzo slaby pomysl. Moze sam cos przegapilem takze wolam @kq @Endrju @satirev

0

A dlaczego niby nie wolno porównywać adresów? Szczególnie że porównywane są adresy obiektów string a nie zaalokowanej pod spodem pamięci. Nie widzę tutaj w zasadzie niczego złego, co najwyżej nie do końca rozumiem logikę takiego zachowania, ale zakładam że jakaś istnieje. Szczególnie że w takich sytuacjach trzeba pamiętać że stos rośnie w drugą stronę więc adres END będzie mniejszy niż adres START ;]

3

Jeśli te adresy nie należą do tego samego obiektu/tablicy to jest to UB.

1

@kq to ciekawe, czemu samo porównanie miałoby być UB? Przecież każdy obiekt posiada jakiś adres w pamięci i nic nie stoi na przeszkodzie żeby takie adresy porównywać. UB byłoby gdyby ktoś próbował wykorzystać ten blok pokazany wyżej jak tablicę i skakać sobie po stosie, ale nic takiego nie widzimy w kodzie.

4

Nie twierdzę, że na znakomitej większości architektur - jeśli nie wszystkich obecnie stosowanych - tak nie jest. Ale standard mówi:

§ 5.9 [expr.rel]/3

Comparing pointers to objects is defined as follows:
(3.1) — If two pointers point to different elements of the same array, or to subobjects thereof, the pointer to the element with the higher subscript compares greater.
(3.2) — If one pointer points to an element of an array, or to a subobject thereof, and another pointer points one past the last element of the array, the latter pointer compares greater.
(3.3) — If two pointers point to different non-static data members of the same object, or to subobjects of such members, recursively, the pointer to the later declared member compares greater provided the two members have the same access control (Clause 11) and provided their class is not a union.

0

Problem polega na tym, że to są stałe do obiektów typu string. Nie są zebrane w żadnej tablicy, ani nie są też elementem żadnej innej klasy. Są po prostu definiowane jeden po drugim.

3

Jak przytoczyłem - jest to opieranie się na (logicznym) zachowaniu kompilatora, które jednak nie jest zdefiniowane w standardzie. Mi się niespecjalnie podoba ta praktyka, ale czasem jest stosowana i zapewne będzie działać.

5

Operatory <, > i reszta nie mają opisanego zachowania dla takich porównań (ale to nie jest undefined behavior, tylko unspecified, 5.9/4). Do takich porównań służy std::less i reszta, która ustanawia total ordering (20.9.5/14).

1

Ktokolwiek napisał oryginalny kod, albo nie wiedział, czym to grozi, albo pisał pod konkretny (co do wersji!) kompilator i sprzęt... Brzydki kod. :)

Nigdzie nie jest powiedziane, że takie zmienne/stałe muszą być alokowane po kolei, a co więcej -- ponieważ są const -- mogą w ogóle nie być alokowane (z powodu optymalizacji w czasie kompilacji; choć oczywiście jakiś adres przypisany będą miały), albo (te które się powtarzają) mogą być zredukowane do jednego obiektu, o tym samym adresie. Nie kłóciłoby się to nijak (chyba) ze specyfikacją typu string w języku C++.

PS. A co to w ogóle za program? Można go zobaczyć w jakimś większym fragmencie?

1 użytkowników online, w tym zalogowanych: 0, gości: 1, botów: 0