Panel użytkownika
Nazwa użytkownika:
Hasło:
Nie masz jeszcze konta?

[C++] Operacje na wskaźniku - kiedy standard określa niezdefiniowane zachowanie?

Ostatnio zmodyfikowano 2015-01-05 21:52
Autor Wiadomość
Krump
» 2015-01-04 01:27:18
Jeszcze niektóre rzeczy na nim się pisze ;) Ale niestety w większości to producenci narzucają, a od zera tworzenie układu cyfrowego jest nieoplacalne.
P-124054
DejaVu
» 2015-01-04 01:42:43
http://timepp.drivehq.com​/cpp11/data/expr.add.html
http:/​/c0x.coding-guidelines.com​/6.5.6.html
http:/​/programmers.stackexchange.com​/questions/247233​/pointer-indexing

1170 If both the pointer operand and the result point to elements of the same array object, or one past the last element of the array object, the evaluation shall not produce an overflow;

1171 otherwise, the behavior is undefined.

Dodatkowo:
The additive operators + and - group left-to-right.

Czyli kompilator wg standardu powinien wykonać takie obliczenia:
C/C++
char tekst[] = "abc";
char * ptr = tekst;
ptr = ptr - 1; // UB (wskaźnik poza tablicą)
ptr = ptr + strlen( tekst );
Czyli zachowanie jest de-facto niezdefiniowane, bo wskaźnik wychodzi poza zakres tablicy.

/edit:
Podsumowując, powyższe paragrafy implikują to co zostało napisane pod adresem http://c-faq.com/aryptr​/non0based.html, czyli:
Pointer arithmetic is defined only as long as the pointer points within the same allocated block of memory, or to the imaginary ``terminating'' element one past it; otherwise, the behavior is undefined, even if the pointer is not dereferenced.

Wspomniane zapisy występują zarówno w standardzie języka C jak i w standardzie języka C++.

/edit2:
W ogóle nie wiem, skąd ta dyskusja, w tym wątku. temat został dawno rozwiązany, a ostatnie strony to tylko jakaś przepychanka. Prosiłbym o pomoc w innych tematach, a nie kłócenie się o rzecz rozwiązaną w tym.
@Krump: wymieniamy się wiedzą, której nie znajdziesz w podręcznikach ani książkach. Ta dyskusja ma sens.
P-124056
SocrateZ
» 2015-01-04 02:00:53
Z powyższego linku (c-faq.com) warto wyciąć również i to zdanie:

The code above computes a pointer to memory before the beginning of realarray and could fail if, while subtracting the offset, an illegal address were generated (perhaps because the address tried to "wrap around" past the beginning of some memory segment).

Czy adres nie zostanie przypadkiem ustalony po wykonaniu całego działania?
P-124059
DejaVu
» 2015-01-04 02:45:12
Operacje dodawania i odejmowania wykonywane są od lewej do prawej (tak jak zacytowałem). To, że nie widać wyników pośrednich nie oznacza, że nie są one 'gdzieś' przechowywane. Wynik pośredni wychodzi poza zakres więc zgodnie ze standardem zachowanie jest niezdefiniowane. Po to są nawiasy () aby wymusić inną kolejność wykonywania działań. W tym wypadku wspomniane nawiasy nie występują, więc kompilator przetworzy te dane w takiej samej kolejności w jakiej użytkownik podał (co jest również zgodne z intuicją).
P-124061
GolemXIV
» 2015-01-04 14:19:30
@antonio:
dziwne że jest błąd bo takie zadania dostaliśmy od prowadzącego

Proponuję założyć, że na tym forum też znajdziesz kilku profesjonalistów. Tyle tylko, że nie wiesz jaki mają tytuł naukowy albo inne osiągnięcia. Poziom wielu odpowiedzi wskazuje na [co najmniej niezłe] kompetencje.

@kaikso:
"U mnie działa" nie jest dobrą miarą poprawności. Bardzo podobne dyskusje, i wiele zmian w kodzie dotyczących walidacji i interpretacji wyników pośrednich miało miejsce przy tworzeniu boost::filesystem.

W skrócie i uproszczeniu: jaka jest pełna nazwa katalogu: /a/.. ?
Zazwyczaj / , ale jeśli filesystem dopuszcza linki (twarde albo miękkie), i /a jest takim linkiem, to może być inaczej. Na podstawie statycznej kontemplacji nazwy nic nie jest pewne (choć z praktyki wynika, że zazwyczaj jest dobrze).
Tak samo tutaj: zazwyczaj (tekst - 1) siedzi w tej samej przestrzeni adresowej (filesystem nie ma linków) albo nie jest walidowany (nikt nie patrzy, co naprawdę znaczy "tekst-1"), to całość zadziała zgodnie ze statyczną kontemplacją wzoru. Zazwyczaj kompilator generuje kod taki, żeby jednak niespodzianki nie robić. Ale nie musi.
P-124071
Kaikso
» 2015-01-04 21:43:10
Czyli kompilator wg standardu powinien wykonać takie obliczenia:
C/C++
char tekst[] = "abc";
char * ptr = tekst;
ptr = ptr - 1; // UB (wskaźnik poza tablicą) //edit: brak operacji na komórce (nie ma UB)
ptr = ptr + strlen( tekst );
Czyli zachowanie jest de-facto niezdefiniowane, bo wskaźnik wychodzi poza zakres tablicy.

Standard C uważa wyrażenie
array[ - 1 ]
 za niezdefiniowane, ponieważ wartość pod tym adresem jest nie określona lub adres jest poza dopuszczalnymi granicami. Więc aby to było niezdefiniowane zachowanie należało by wykonać operację na owym adresie, więc gdybyśmy wykonali operację
ptr = & array[ - 1 ];
 kompilator mógłby wygenerować kod który najpierw odczytuje wartość z pod podanego adresu (niezdefiniowane zachowanie), a osobno podać adres określonego elementu. Ale jeśli operujemy jedynie na wartości samego wskaźnika tj. bez użycia operatorów pobrania wartości z tablicy lub wyłuskania nie możliwa jest sytuacja w której ten kod spowoduje wystąpienie niezdefiniowanego zachowania.

PS. http://c-faq.com/aryptr​/non0based.html opisuje kod w którym jest użyty operator pobrania wartości z tablicy (możliwe wystąpienie UB), a następnie pobrania adresu tej wartości, otrzymany adres pozostaje w stanie nie określonym (dalsze operacje na nim mogą spowodować UB).
P-124152
GolemXIV
» 2015-01-04 22:39:44
Był kiedyś taki archaiczny procesor 8086 (i jego bliscy kuzyni, od 8088 aż do 80286).
Adresowanie pamięci w nim było cokolwiek skomplikowane - to co znamy jako liniowe adresowanie to był model "huge", wcale nie defaultowy, bo zmuszał procesor do nadzwyczajnego wysiłku dla symulowania liniowej adresacji. Programy użytkownika były odpalane w ring-2, a nad wszystkim czuwał OS (w ring-0). W tych prehistorycznych czasach nawet nie można było porównywać wskaźników, nawet w relacji równe/nierówne, bo wyniki były ... nieokreślone :)
Jeśli "tablica" leżała na samym brzegu segmentu (offset 0), to arytmetyka z podanego przykładu mogła pobudzić supervisora do działania.
P-124157
DejaVu
» 2015-01-05 09:46:08
Ale jeśli operujemy jedynie na wartości samego wskaźnika tj. bez użycia operatorów pobrania wartości z tablicy lub wyłuskania nie możliwa jest sytuacja w której ten kod spowoduje wystąpienie niezdefiniowanego zachowania.
No proszę Cię... przeczytaj przytoczone cytaty ze standardu, a nie tu cały czas własną teorię wygłaszasz. Standard mówi 'niezdefiniowane zachowanie' i koniec. W przytoczonych fragmentach tekstu jest mowa tylko i wyłącznie o poprawności obliczania wskaźnika, a nie o jakiejś tam dereferencji na którą się powołujesz.
P-124182
1 2 3 4 5 6 « 7 » 8
Poprzednia strona Strona 7 z 8 Następna strona