definierte und undefinierte Codekonstrukte
-
Hi
Mein Problem ist es für eine Aufgabe fünf versch. C++-Konstrukte deren Bedeutung undefiniert ist und fünf versch. C++-Konstrukte deren Bedeutung implementierungsabhängig ist, zu finden. Ich hab aber keine Ahnung wie ich da rangehen kann, bzw, wie ein mögliches Ergebnis aussehen kann, mir fällt auf Anhieb nurint a, b; a = b++;
ein, dessen Bedeutung afaik implementierungsabhängig ist. Es kommt glaub ich auf den Compiler drauf an, was da rauskommt. Was hättet Ihr da so als Antwort zu bieten?!
Dann soll ich noch 10 Beispiele von nichtportablem C++ Code finden, meine Frage hierzu: kann man hier zB alle Funktionen aufführen, die zB nur unter <windows.h> definiert sind?
Danke.
-
Das Ergebnis ist nur insofern implementierungsabhängig, als dass es darauf ankommt, wie der Kompiler deine Variablen initialisiert. Normalerweise sollte er sie aber garnicht initialisieren. Es sollte eigentlich der Wert an der Adresse verwendet werden, der schon dort steht.
-
int a, b;
ist klar definiert, nämlich im globalen Bereich a und b = 0 und lokal *irgendetwas*. Bzw. es ist definiert, dass das Ergebnis undefiniert ist.
Das ist echt mal 'ne dämliche Aufgabenstellung.
-
hm...
man könnte vieleichtvirtual
aufführen... da bleibt es dem Compilerhersteller überlassen, wie er es impletiert... (ist das damit gemeint ?)
-
Zu implementierungsabhängig:
Hier gab es letztens einen Thread zu type_id().name()."Undefiniert" und "implementationsabhängig" halte ich aber für sehr schwammig.
Viele undefinierte Konstrukte funktionieren bei einer bestimmten Implementierung; sind sie deswegen implementierungsabhängig?
-
class X {}; const int Xsize = sizeof(X);
Der Wert von a ist zwar immer ungleich 0, aber AFAIK implementierungsabhängig.
-
cd9000 schrieb:
class X {}; const int Xsize = sizeof(X);
dasselbe kann man noch mit
struct Y {} //...
dann hat man schon 2
-
undefined und unspecified sind Sachen, die sich nicht der Aufgabensteller ausgedacht hat, sondern die in der Sprachspezifikation so beschrieben sind. "RAND_MAX" und "vector<T>::iterator" sind unspezifiziert (innerhalb einer Implementierung konsistent und logisch passend), "int* i; *i = 5;" ist undefiniert (hier kann jedes Mal alles passieren).
Und das Beispiel mit dem Postfix-Inkrement sollte wohl sein:int i = 1337; i = i++;
Da ist die Ausführungsreihenfolge nämlich unspezifiziert.
Habe ich jetzt zuviel verraten?
-
register
das ist auch vom Compiler abhängig...fals ich hier jetzt auf dem richtigen Pfad bin
-
Online schrieb:
register
das ist auch vom Compiler abhängig...fals ich hier jetzt auf dem richtigen Pfad bin
inwiefern ist es vom compiler abhängig?
-
operator void schrieb:
Und das Beispiel mit dem Postfix-Inkrement sollte wohl sein:
int i = 1337; i = i++;
Da ist die Ausführungsreihenfolge nämlich unspezifiziert.
Sicher? Ich dachte, es sei spezifiziert, dass zuerst der alte Wert von i zurückgegeben wird und dann i um 1 erhöht wird.
-
Shade Of Mine schrieb:
Online schrieb:
register
das ist auch vom Compiler abhängig...fals ich hier jetzt auf dem richtigen Pfad bin
inwiefern ist es vom compiler abhängig?
Ich glaube, der Compiler muss dieses Schlüsselwort garnicht beachten und kann selbst entscheiden, was er registered macht und was net.
-
a=b*c; ist auch implementierungsabhängig
-
dEUs schrieb:
Ich glaube, der Compiler muss dieses Schlüsselwort garnicht beachten und kann selbst entscheiden, was er registered macht und was net.
ja schon. aber was hat das mit implementations spezifischem verhalten zu tun.
register ändert ja nicht das verhalten des codes.
wie leuchtturm schon gesagt hat, dann wäre auch a=b*c; implementations abhängig. denn was macht der compiler damit?
ein mul? viele add? oder ein geiler trick?
-
operator void schrieb:
undefined und unspecified sind Sachen, die sich nicht der Aufgabensteller ausgedacht hat, sondern die in der Sprachspezifikation so beschrieben sind. "RAND_MAX" und "vector<T>::iterator" sind unspezifiziert (innerhalb einer Implementierung konsistent und logisch passend), "int* i; *i = 5;" ist undefiniert (hier kann jedes Mal alles passieren).
Und das Beispiel mit dem Postfix-Inkrement sollte wohl sein:int i = 1337; i = i++;
Da ist die Ausführungsreihenfolge nämlich unspezifiziert.
Habe ich jetzt zuviel verraten?
Das Beispiel ist nicht unspezifiziert sondern undefiniert, denn:
Between the previous and next sequence point an object shall have its stored value modified at most once by the evaluation of an expression. Furthermore, the prior value shall be read only to determine the value to be stored
Hier gibt es nur einen Sequence-Point, namlich am Ende der gesamten Anweisung (quasi das Semikolon). Bis dahin wir der Wert von i aber zweimal geändert und zweimal gelesen -> undefiniert.
Unspezifiziet ist sowas:
*p++ = *q++
Hier ist nicht festgelegt, in welcher Reihenfolge die Seiteneffekte auftreten.
Möglich ist z.B.
*p = *q;
++p;
++q;oder
*p = *q;
++q;
++p;Ein anderes Beispiel für unspezifiziert ist (aus Exceptional C++):
int f(int& x, int y = 1) {return x += y;} int g(int& x) {return x/=2;} int main() { int i = 42; cout << "f(" << i << ") = " << f(i) << ", " << "g(" << i << ") = " << g(i) << endl; }
Hier ist das Ergebnis abhängig von der Reiehnfolge der Parameterauswertung, welche im Standard nicht festgelegt ist.
Ist gibt übrigens noch einen unterschied zwischen "unspecified" und "implementation-defined". "Implementation-defined behavior" muss von der Implementation dokumentiert werden. "unspecified behavior" hingegen nicht. Angewandt auf das obere Beispiel bedeutet dies, dass in der Compilerdoku nicht stehen muss, in welcher Reihenfolge der Compiler Funktionsparameter auswertet.
}
-
cd9000 schrieb:
"Undefiniert" und "implementationsabhängig" halte ich aber für sehr schwammig.
Viele undefinierte Konstrukte funktionieren bei einer bestimmten Implementierung; sind sie deswegen implementierungsabhängig?Im Kontext von Standard-C++ sind die Begriffe keineswegs schwammig. Sie werden im Standard eindeutig definiert (1.3.5, 1.3.12 sowie 1.3.13)
-
Hallo,
Toll - so viele Antworten!!!!!
Aus dem Grunde auch schon mal, weil das eigentlich eine
Anfängeraufgabe ausm Stroustrup is, die aber anscheinend
doch auch zu Diskussionen führt unter Fortgeschrittenen.Ich hab nun weiter hinten in dem Buch unter C2 noch
folgendes dazu gefunden und wollte es mal der
Vollständigkeit halber noch anführen:unsigned char c1 = 64; // wohldefiniert, ein char hat mind 8 Bit unsigned char c2 = 1256; // implementierungsspezifisch // ... und ... const int size = 4*1024; char page[size]; void f() { page[size+size] = 7; // undefiniert }
...sind allerdings eben nur 2 Bsps und nicht 5, aber nun is mir klarer
in welche Richtung das gehen soll.Danke Euch nochmal!
-
int i = 2; cout << i++ << (i++) * (i++);
Ist ebenfalls undefiniert.
-
Hi,
bei
struct undef { int a; char b; long c; }
ist auch undefiniert, in welcher Reihenfolge die Objecte im Speicher abgelegt werden.
(daher kann man um alles auf 0 zu setzen nicht die Funktion mamset() benutzen, der man als Startadresse die Adresse von undef.a übergibt, und als Anzahl der zu überschreibenden Bytes sizeof(int) + sizeof(char) + sizeof(int).
-
c++eus schrieb:
Hi,
bei
struct undef { int a; char b; long c; }
ist auch undefiniert, in welcher Reihenfolge die Objecte im Speicher abgelegt werden.
(daher kann man um alles auf 0 zu setzen nicht die Funktion mamset() benutzen, der man als Startadresse die Adresse von undef.a übergibt, und als Anzahl der zu überschreibenden Bytes sizeof(int) + sizeof(char) + sizeof(int).das mit den padding bytes stimmt.
aber es ist schon definiert, dass a vor b vor c kommt. sonst wäre es ja ein blödsinn.