CPP-Klausur
-
Wann "++" ausgewertet wird ist in diesem Fall klar definiert. Nämlich nachdem der Wert von
(*p)ermittelt wird -- steht ja hinten und nicht vorn dran.Was zu UB führt ist dass hier "ungültige" Zeiger erzeugt und dann obendrein noch dereferenziert werden.
-
hardware schrieb:
soweit ich das verstehe, meint Arcoth solche Sachen:
int n = (*p)++;weil nicht definiert ist, ob das ++ vor oder nach der Zuweisung geschieht. Korrigiert mich wenns falsch ist.
ist falsch.
int main() { int m=44; int *p=&m; // int &r=m; // int n=(*p)++; int *q=p-1; // r=*(--p)+1; ++*q; // ^ (zeigt eins vor 'int m' -> UB) cout << n << endl << &m << endl << *p << endl << r << endl << *q; // ^ (zeigt eins vor 'int m' -> UB) return 0; }
-
ok danke, da hab ich was falsches gemerkt, sehe jetzt auch das eigentliche UB.
-
Das UB passiert beim p-1, denn 1 von p abzuziehen ist hier nicht erlaubt.
-
Arcoth schrieb:
Das UB passiert beim p-1, denn 1 von p abzuziehen ist hier nicht erlaubt.
N3337 schrieb:
5.7 Additive operators
2) `For subtraction, one of the following shall hold:— both operands have arithmetic or unscoped enumeration type; or
— both operands are pointers to cv-qualified or cv-unqualified versions of the same completely-defined
object type; or
— the left operand is a pointer to a completely-defined object type and the right operand has integral or
unscoped enumeration type.
`
[...]
For the purposes of these operators, a pointer to a nonarray object behaves the same as a pointer to the first element of an array of length one with the type of the object as its element type.
so weit ich das sehe, ist also
T a; T* b = &a-1;kein UB sondern lediglich impl.defined behaviour (was inbbzw*bsteht). UB wirds damit erst beim Zugriff auf b.oder lieg ich da falsch?
bb
-
#include <iostream> using namespace std; int main() { int m = 44; int *p = &m; int &r = m; int n = *(p)++; int *q = p - 1; r = *(--p) + 1; ++*q; cout << n << endl << &m << endl << *p << endl << r << endl << *q; return 0; }So funktioniert es einwandfrei...

-
unskilled schrieb:
so weit ich das sehe, ist also
T a; T* b = &a-1;kein UB sondern lediglich impl.defined behaviour (was inbbzw*bsteht). UB wirds damit erst beim Zugriff auf b.oder lieg ich da falsch?
Soweit ich weiss liegt du da falsch.
IIRC ist sogar das UB:int* p = new int(42); delete p; int* p2 = p; // <-- UBUnd analog dazu auch
int* p = new int(42); int* p2 = p - 1; // <-- UBund auch
int i; int* p = &i; int* p2 = p - 1; // <-- UB
-
mrv3112 schrieb:
#include <iostream> using namespace std; int main() { int m = 44; int *p = &m; int &r = m; int n = *(p)++; int *q = p - 1; r = *(--p) + 1; ++*q; cout << n << endl << &m << endl << *p << endl << r << endl << *q; return 0; }So funktioniert es einwandfrei...

Na sowas.
Ist ja auch ganz anderer Code.
*(p)++ist nicht das selbe wie(*p)++UB ist es allerdings vermutlich immer noch. (Oder gilt die "one past last" Ausnahme für alle Objekte und nicht nur für Arrays?)
-
hustbaer schrieb:
IIRC ist sogar das UB:
int* p = new int(42); delete p; int* p2 = p; // <-- UBUnd analog dazu auch
int* p = new int(42); int* p2 = p - 1; // <-- UBund auch
int i; int* p = &i; int* p2 = p - 1; // <-- UBKannst du mir nochmal erklären, was das UB jetzt genau auslöst?
Liegt das hier daran, dass mir der der Speicher vor p ggf nicht gehört oder ist das generell nicht erlaubt?int i1; int i2; int* p = &i2; int* pvor = p - 1; // <-- auch UB ?
-
int* p = new int(42); delete p; int* p2 = p;UB in C++03, implementation-defined ab C++11 (using invalid pointer value)
int* p = new int(42); p - 1;UB da p und p-1 nicht auf Elemente (bzw. 1 nach dem letzten Element) des gleichen Arrays zeigen
int i1; int i2; int* p = &i2; int* pvor = p - 1; // <-- auch UB ?Kein Unterschied. Die Tatsache, dass eine bestimmte Implementation sich möglicherweise dazu entscheidet, i1 unmittelbar vor i2 anzulegen (und dann ist das Ergebnis nat. definiert, weil p gleichzeitig auf eins-hinter-i1 zeigt), bedeutet nicht, dass der Standard das generell verlangt.
-
Ok, danke für die Klarstellung.
-
hustbaer schrieb:
UB ist es allerdings vermutlich immer noch. (Oder gilt die "one past last" Ausnahme für alle Objekte und nicht nur für Arrays?)
siehe mein post. gilt auch für (nicht-array) objekte. sollte somit well defined sein:
#include <iostream> using namespace std; int main() { int m = 44; int *p = &m; //*p = &m int &r = m; //r = m int n = *(p)++; //p = &m+1; n = 44 int *q = p - 1; //q = &m r = *(--p) + 1; //p = &m //r=m=45 ++*q; //q=r=m=46 cout << n << endl << &m << endl << *p << endl << r << endl << *q; //ok //44 //[&m] (adresse von m) //46 //46 //46 return 0; }