Wynik niektórych rzutów wskaźnika jest opisany jako nieokreślony. Na przykład [expr.static.cast]/13Jak zachowuje się nieokreślona konwersja wskaźnika w C++ 14?
prvalue typu „wskaźnik do CV1 próżni” może być przekształcony w prvalue typu „wskaźnik do CV2 T” [...] Jeżeli oryginalna wartość wskaźnika reprezentuje adres A bajtu w pamięci, a A spełnia wymóg wyrównania T, a wynikowa wartość wskaźnika reprezentuje ten sam adres, co oryginalna wartość wskaźnika, czyli A. Wynik dowolnego innego takiego wskaźnika konwersja jest nieokreślona.
Moje pytanie brzmi: w przypadku, gdy ustawienie jest nie spełnione, jakie są możliwe wyniki?
Czy na przykład dozwolone są następujące wyniki?
- null pointer
- nieprawidłowa wartość wskaźnika (czyli wskaźnik, który nie wskazuje na przydzielonej przechowywania wielkości
T
) - ważny wskaźnik do
T
w zupełnie oddzielnej części pamięci
przykładowy kod dla odniesienia:
#include <iostream>
int main(int argc, char **argv)
{
int *b = (int *)"Hello, world"; // (1)
*b = -1; // (2)
std::cout << argc << '\n';
}
Linia (1)
wyzwala mój powyższy cytat z [expr.static.cast]/13, ponieważ jest to reinterpret_cast
która jest objęta [expr.reinterpret.cast]/7, który określa konwersję w zakresie static_cast
ing przez void *
.
Jeśli nieokreślony wynik może być nieprawidłową wartością wskaźnika, linia (1)
może spowodować pułapkę sprzętową. (Numer referencyjny: N4430, który wyjaśnia podobne sformułowanie w C++ 14 i C++ 11).
Pytanie uzupełniające: Czy istnieje przypadek, w którym linia 1
spowodowałaby niezdefiniowane zachowanie? (Nie sądzę, na tym etapie, ponieważ odczyt wartości wskaźnika C++ 14 jest zdefiniowany przez implementację lub powoduje pułapkę sprzętową).
Również interesujące jest to, że linia (2)
będzie w większości przypadków być niezdefiniowane zachowanie ze względu na ścisłą naruszeniem aliasing (i być może innych przyczyn zbyt), jednak jeśli nieokreślony wynik może być &argc
to ten program może wyjście -1
bez wyzwalania niezdefiniowany zachowanie!
Err, jest nieokreślony. – EJP
"... wtedy ten program mógłby wypisać' -1' bez wywoływania niezdefiniowanego zachowania "to dziwne - i powiedziałbym niewłaściwe - sposób na wyrażenie go. Linia (2) zawsze powoduje niezdefiniowane zachowanie. "Niezdefiniowane zachowanie" oznacza, że każde zachowanie programu będzie zgodne ze specyfikacją, w tym zachowanie wyjścia -1. "Nieokreślona wartość" jest wartością (nie zachowaniem), której specyfikacja nie ogranicza, a implementacja nie musi dokumentować. – Nemo
@Noo w jaki sposób linia 2 powoduje UB (jeśli 'b' ma wartość' & argc') –