mikrocontroller.net

Forum: PC-Programmierung * C++ == C++ *


Autor: freitagsposter (Gast)
Datum:

Bewertung
-5 lesenswert
nicht lesenswert
@mod bitte verschieben wenn unpassendes forum "code"


viel spass beim freitagsabtausch




void main (void) {

 int C;

 if ( C++ == C++ ) {
  print ( "A is A\n" );
  } else {
  print ( "A is not A\n");
 }
}



: Verschoben durch Moderator
Autor: Joachim D. (Firma: JDCC) (scheppertreiber)
Datum:

Bewertung
-1 lesenswert
nicht lesenswert
A is not A

Autor: Yalu X. (yalu) (Moderator)
Datum:

Bewertung
4 lesenswert
nicht lesenswert
Da meckert schon der Compiler bzw. Linker:
implicit declaration of function ‘print’

undefined reference to `print'

Ersetzt ma  print durch printf und inkludiert stdio.h, bleibt immer noch
eine Warnung
‘C’ is used uninitialized in this function

Selbst wenn man C intialisiert, meckert der Compiler:
operation on ‘C’ may be undefined

Der Ausdruck C++ == C++ ist nämlich gar nicht erlaubt, da er
undefiniertes Verhalten bewirkt.

Diese Diskussion um undefiniertes Verhalten – insbesondere im
Zusammenhang mit den Operatoren ++ und --, hatten wir hier aber schon
oft.


PS: Der Clang-Compiler erläutert das Problem noch etwas dataillierter:
warning: multiple unsequenced modifications to 'C' [-Wunsequenced]
  if ( C++ == C++ ) {
        ^      ~~

Es sind also tatsächlich die beiden ++, die sich gegenseitig beißen.

: Bearbeitet durch Moderator
Autor: Maximilian S. (maxst)
Datum:

Bewertung
-2 lesenswert
nicht lesenswert
Dass der Compiler da meckert ist ja klar. Das sollte eher eine kleine 
Denkaufgabe sein , die sich als gar nicht mal so einfach herausstellt.
Ich nehme mal an C wird einfach irgendwo im Speicher festgelegt und hat 
halt einen bestimmten wert. Man muss sich nun ziemlich gut mit C 
auskennen um genau sagen zu können wie und wann welche Befehle 
ausgeführt werden.

Mein Output :

A is not A

Autor: Peter II (Gast)
Datum:

Bewertung
3 lesenswert
nicht lesenswert
Maximilian S. schrieb:
> Man muss sich nun ziemlich gut mit C
> auskennen um genau sagen zu können wie und wann welche Befehle
> ausgeführt werden.

das hat aber wenig mit C zu tun. Man muss maximal seinen Compiler 
kennen. Denn hier kann jeder Compiler etwas anderes liefern. (sogar jede 
Version vom Compiler)

Autor: C-Kenner (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Weil man eine Variable nur einmal pro Sequencepoint zuweisen darf. Ein 
Sequencepoint ist der Punkt ab dem eine Zuweisung zu einer Variablen für 
den Rest des Programm sichtbar wird. Beispielsweise ist jedes ';' ein 
solcher.

Autor: Yalu X. (yalu) (Moderator)
Datum:

Bewertung
4 lesenswert
nicht lesenswert
Peter II schrieb:
> Denn hier kann jeder Compiler etwas anderes liefern. (sogar jede
> Version vom Compiler)

Und sogar ein und der selbe Compiler in unterschiedlichen
Optimierungsstufen.

Es ist nicht einmal garantiert, dass das Programm überhaupt etwas
ausgibt. Es könnte (zumindest theoretisch) sogar passieren, dass bei der
Ausführung des Programms die Festplatte komplett gelöscht wird :)
Selbst in diesem Fall wäre der Compiler immer noch ISO-konform.

Autor: freitagsposter (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
na dann nächste runde Yalu
und auf die festplatte aufpassen!
;-)


int main( int c, char *v[]) {
 
  struct {
   unsigned long x : 33;
  } s;

  typedef typeof(0+s.x) uint33;
  
  uint33 y = -1;
  
  printf("%lu\n\n", (unsigned long)y);
  
  uint33 t[3] = { 0x100000000 };
  t[1] = t[0] + 1;
  t[2] = t[0] + t[1];
  
  for (int i = 0; i<3; i++)
    printf("%9lx\n", (unsigned long)t[i]);
  
}


gcc t.c && ./a.outp

??

Autor: freitagsposter (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
alles ist möglich!

Autor: freitagsposter (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
sicher den rechtschreibpatzer bemerkt aber vorsichtshalber:

das 'p' am ende war zuviel


gcc t.c && ./a.out


??

Autor: freitagsposter (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
8589934591

100000000
100000001
        1


;-)

Autor: Frank M. (ukw) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
freitagsposter schrieb:
> gcc t.c && ./a.out
$ gcc t.c  && ./a.out
t.c: In function 'main':
t.c:6:4: error: width of 'x' exceeds its type
t.c:15:3: warning: large integer implicitly truncated to unsigned type [-Woverflow]
t.c:19:3: error: 'for' loop initial declarations are only allowed in C99 mode
t.c:19:3: note: use option -std=c99 or -std=gnu99 to compile your code
$ gcc -std=c99 t.c && ./a.out
t.c: In function 'main':
t.c:6:4: error: width of 'x' exceeds its type
t.c:9:18: error: expected declaration specifiers or '...' before numeric constant
t.c:11:3: error: unknown type name 'uint33'
t.c:15:3: error: unknown type name 'uint33'
t.c:15:3: warning: overflow in implicit constant conversion [-Woverflow]

Außerdem hast Du ein

#include <stdio.h>

vergessen ;-)

: Bearbeitet durch Moderator
Autor: freitagsposter (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Frank M. schrieb:

> freitagsposter schrieb:
>> gcc t.c && ./a.out$ gcc t.c  && ./a.out
> t.c: In function 'main':
> t.c:6:4: error: width of 'x' exceeds its type
> t.c:15:3: warning: large integer implicitly truncated to unsigned type
> [-Woverflow]
> t.c:19:3: error: 'for' loop initial declarations are only allowed in C99
> mode
> t.c:19:3: note: use option -std=c99 or -std=gnu99 to compile your code
> $ gcc -std=c99 t.c && ./a.out
> t.c: In function 'main':
> t.c:6:4: error: width of 'x' exceeds its type
> t.c:9:18: error: expected declaration specifiers or '...' before numeric
> constant
> t.c:11:3: error: unknown type name 'uint33'
> t.c:15:3: error: unknown type name 'uint33'
> t.c:15:3: warning: overflow in implicit constant conversion [-Woverflow]


dann taugt dein compiler (einstellung) nicht für ein 33 bit integer type

Autor: freitagsposter (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
das wäre die richtige antwort

;-)

Autor: Frank M. (ukw) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
freitagsposter schrieb:
> dann taugt dein compiler (einstellung) nicht für ein 33 bit integer type

Bewahrt mich aber auch vor Unsinn ;-)

Autor: freitagsposter (Gast)
Datum:

Bewertung
1 lesenswert
nicht lesenswert
Frank M. schrieb:
> freitagsposter schrieb:
>> dann taugt dein compiler (einstellung) nicht für ein 33 bit integer type
>
> Bewahrt mich aber auch vor Unsinn ;-)

nur der mut zählt ;-)

Autor: Daniel A. (daniel-a)
Datum:

Bewertung
1 lesenswert
nicht lesenswert
Yalu X. schrieb:
> Es könnte (zumindest theoretisch) sogar passieren, dass bei der
> Ausführung des Programms die Festplatte komplett gelöscht wird :)

Gibts soeinen Compiler schon? Wäre ne coole ergänzung zu Suicide Linux: 
https://qntm.org/suicide, perfekt für den real programmer ;)

Autor: freitagsposter (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Frank M. schrieb:
> t.c: In function 'main':
> t.c:6:4: error: width of 'x' exceeds its type
> ...

.LC0:
        .string "%lu %lu\n\n"
.LC1:
        .string "%9lx\n"
main:
        subq    $8, %rsp
        movabsq $8589934590, %rdx
        movabsq $8589934591, %rsi
        movl    $.LC0, %edi
        xorl    %eax, %eax
        call    printf
        movabsq $4294967296, %rsi
        movl    $.LC1, %edi
        xorl    %eax, %eax
        call    printf
        movabsq $4294967297, %rsi
        movl    $.LC1, %edi
        xorl    %eax, %eax
        call    printf
        movl    $1, %esi
        movl    $.LC1, %edi
        xorl    %eax, %eax
        call    printf
        xorl    %eax, %eax
        addq    $8, %rsp
        ret


x86-64 gcc 6.1
-xc -O2

Autor: freitagsposter (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
und jetzt?
// dont forget this!!
// ;-)
#include <stdio.h>

int main(int c, char *v[])
{
  struct {
    unsigned long x : 33;
  } s;

  typedef typeof(0+s.x) uint33;

  uint33 y = -1;

  printf("%lu %lu\n\n", (unsigned long)y, (unsigned long)(y + y));

  uint33 t[3] = { 0x100000000 };
  t[1] = t[0] + 1;
  t[2] = t[0] + t[1];

  for (int i = 0; i<3; i++)
    printf("%9lx\n", (unsigned long)t[i]);
  
}

Autor: steinadler (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
VS2012 C# kompiliert das ohne Probleme bzw. Warnung.

Natürlich "A is not A"

Autor: steinadler (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
            int c = 5;
            int pascal = 5;

            if (c++ == pascal)
            {
print ( "C++ is Pascal\n" );
            }
            else
            {
print ( "C++ is not Pascal\n" );
            }

Ist auch interessant ;-)

Autor: Jörg W. (dl8dtl) (Moderator) Benutzerseite
Datum:

Bewertung
1 lesenswert
nicht lesenswert
Daniel A. schrieb:
> Yalu X. schrieb:
>> Es könnte (zumindest theoretisch) sogar passieren, dass bei der
>> Ausführung des Programms die Festplatte komplett gelöscht wird :)
>
> Gibts soeinen Compiler schon?

Zumindest hat GCC in frühen Versionen in solchen Fällen auch schon
mal "nethack" gespielt. :-)

http://feross.org/gcc-ownage/

Autor: Yalu X. (yalu) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
freitagsposter schrieb:
> na dann nächste runde Yalu
> und auf die festplatte aufpassen!
> ;-)

Ja, das ist schon interessanter :)

Dazu muss erst einmal gesagt werden, dass der typeof-Operator kein
ISO-C, sondern eine GNU-Erweiterung ist.

Auch unsigned-long-Bitfelder sind Erweiterungen, die allerdings in der
ISO-Norm explizit erlaubt werden.

Leider kann ich in der Norm auf die Schnelle keine Informationen darüber
finden, welchen Typ einzelne Bitfelder haben, wenn sie bspw. in
arithmetischen Ausdrücken verwendet werden. Bei Bitfeldern mit
erweiterten Datentypen (im vorliegenden Fall unsigned long int) scheint
der GCC mit Integer-Typen mit "krummen" Bitbreiten zu arbeiten (hier mit
"unsigned long int:33"). Im Gegensatz dazu haben beim Clang diese
Bitfelder den Typ unsigned long int, weswegen das Verhalten der beiden
Compiler an dieser Stelle unterschiedlich ist. Folgender Code

#include <stdio.h>

int main(void) {
 
  struct {
   unsigned long x : 33;
  } s = { 0x1ffffffff };

  printf("%9lx\n", (unsigned long)s.x);
  printf("%9lx\n", (unsigned long)(s.x + 1));
  printf("%9lx\n", (unsigned long)(2*s.x));
}

liefert mit dem GCC:

1ffffffff
        0
1fffffffe

Die Ergebnisse werden also auf 33 Bit gestutzt.

Beim Clang ist das nicht der Fall, da hier für die Berechnungen
offensichtlich die volle Breite von 64 Bit genutzt wird:

1ffffffff
200000000
3fffffffe

Welcher der beiden Compiler nun recht hat, kann ich nicht sagen.
Möglicherweise beide, da es hier ja um eine C-Erweiterung geht, bei
denen die Norm den Compilern üblicherweise viel Freiheit lässt.
Vielleicht findet aber auch jemand die Stelle in der Norm, wo solche
Dinge genauer geregelt sind.

Was das typeof betrifft: Witzigerweise kann man – wie in deinem Beispiel
gezeigt – über dem Umweg über ein Bitfeld in einer Struktur und typeof
auch ganz gewöhnliche Variablen als Bitfeld deklarieren, so dass bei der
Arthmetik mit solchen Variablen die Ergebnisse ebenfalls auf eine krumme
Bitzahl beschnitten werden.

Das Ganze betrifft aber wohlbemerkt nur Bitfelder, die größer als int
und damit C-Erweiterungen sind. Ein int-Bitfeld wird – unabhängig von
der tatsächlichen Bitzahl – in Ausdrücken immer auf ein int erweitert.
Somit sollten sich die beiden Compiler in diesem Fall gleich verhalten.

Autor: Rolf M. (rmagnus)
Datum:

Bewertung
4 lesenswert
nicht lesenswert
Es ist müßig, eine "Denksportaufabe" zu undefiniertem Verhalten zu 
machen, denn: Sobald das ins Spiel kommt, ist jedes beliebige Ergebnis 
richtig. Es wäre sogar korrekt, wenn das Programm bei dieser if-Abfrage 
beide Zweige (also sowohl if, als auch else) ausführt, oder wenn es 
abstürzt oder eine unfreundliche E-Mail an deinen Chef sendet. In 
comp.lang.c wurden als Beispiel immer Dämonen, die aus deiner Nase 
kommen, genannt. Auch die wären nach ISO-C ein korrektes Ergebnis. ;-)

Autor: Günter X. (kolle)
Datum:

Bewertung
-2 lesenswert
nicht lesenswert
Joachim D. schrieb:
> A is not A

Öhm nöö.

A is A

Erst wird verglichen, dann wird erhöht, zweimal.

Autor: Jörg W. (dl8dtl) (Moderator) Benutzerseite
Datum:

Bewertung
1 lesenswert
nicht lesenswert
Günter X. schrieb:
> Erst wird verglichen, dann wird erhöht, zweimal.

Nein. Genau das ist eben nirgends so festgelegt.

Es ist nur festgelegt, dass nach dem Vergleich C um zwei erhöht
worden sein muss (naja, mal von der fehlenden Initialisierung
abgesehen, die natürlich auch zu undefiniertem Verhalten führt –
insbesondere dann, wenn C beispielsweise vorher zufällig MAX_INT
war).

Autor: Yalu X. (yalu) (Moderator)
Datum:

Bewertung
1 lesenswert
nicht lesenswert
Jörg W. schrieb:
> Es ist nur festgelegt, dass nach dem Vergleich C um zwei erhöht
> worden sein muss

Streng genommen nicht einmal das. Undefined ist undefined, da ist
einfach jede Annahme, egal wie plausibel sie klingen mag, potentiell
falsch.

Autor: Jörg W. (dl8dtl) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Yalu X. schrieb:
> Streng genommen nicht einmal das. Undefined ist undefined

Stimmt auch wieder.

Autor: dulnik (Gast)
Datum:

Bewertung
-2 lesenswert
nicht lesenswert
Jörg W. schrieb:
> Günter X. schrieb:
>> Erst wird verglichen, dann wird erhöht, zweimal.
>
> Nein. Genau das ist eben nirgends so festgelegt.
>
> Es ist nur festgelegt, dass nach dem Vergleich C um zwei erhöht
> worden sein muss (naja, mal von der fehlenden Initialisierung
> abgesehen, die natürlich auch zu undefiniertem Verhalten führt –
> insbesondere dann, wenn C beispielsweise vorher zufällig MAX_INT
> war).

Was NACH dem Vergleich passiert ist sowieso uninteressant, weil der 
Zustand von C nirgendwo im Programmchen abgefragt wird. BEIM Vergleich, 
VOR den beiden post increments, ist C auf jedem Fall gleich C.

Die Antwort lautet daher "A is A".

Autor: Jörg W. (dl8dtl) (Moderator) Benutzerseite
Datum:

Bewertung
2 lesenswert
nicht lesenswert
dulnik schrieb:
> Die Antwort lautet daher "A is A".

Noch einer, der's nicht kapieren will …

Autor: Yalu X. (yalu) (Moderator)
Datum:

Bewertung
1 lesenswert
nicht lesenswert
dulnik schrieb:
> Die Antwort lautet daher "A is A".

Dann musst du sofort einen Bug-Report an die GCC- und Clang-Entwickler
schreiben. Mit diesen Compilern ist die Ausgabe nämlich "A is not A".

Nein, besser nicht ... war nur ein Scherz :)

Autor: Bernd K. (prof7bit)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Yalu X. schrieb:
> PS: Der Clang-Compiler erläutert das Problem noch etwas dataillierter:
> warning: multiple unsequenced modifications to 'C' [-Wunsequenced]
>   if ( C++ == C++ ) {
>         ^      ~~

Auch der gcc kann das (-Wall -Wextra)

warning: operation on 'c' may be undefined [-Wsequence-point]
     if (c++ == c++) {
                 ^

: Bearbeitet durch User
Autor: Mano W. (Firma: ---) (manow)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Egal was da ausgegeben wird bzw. ob überhaupt was ausgeben wird, solchen 
Code schreibt man nicht (in mehrere Hinsicht) und @freitagsposter sollte 
einen auf den Deckel bekommen...

Autor: Bernd K. (prof7bit)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
steinadler schrieb:
> int c = 5;
>             int pascal = 5;
>
>             if (c++ == pascal)
>             {
> print ( "C++ is Pascal\n" );
>             }
>             else
>             {
> print ( "C++ is not Pascal\n" );
>             }
>
> Ist auch interessant ;-)

Was ist daran interessant, was will der Künstler damit zum Ausdruck 
bringen?

Autor: dulnik (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Jörg W. schrieb:
> dulnik schrieb:
>> Die Antwort lautet daher "A is A".
>
> Noch einer, der's nicht kapieren will …

OK, ich habe zu schnell aus der Hüfte geschossen :-) Aber woran liegt 
das genau? Ich dachte die post inkrement operatoren werden nach dem 
Vergleich ausgeführt? Ist der Vergleich keine Expression im Sinne der 
Increment Funktionalität?

Autor: Jörg W. (dl8dtl) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
dulnik schrieb:

> OK, ich habe zu schnell aus der Hüfte geschossen :-) Aber woran liegt
> das genau?

Daran, dass du eben innerhalb einer Anweisung nur maximal eine
Veränderung an einem Objekt durchführen darfst, egal ob nun durch
Zuweisung, pre- oder post-In- oder Dekrement-Operatoren.

Alles andere bewirkt gemäß Standard undefiniertes Verhalten.

Der Hintergrund ist einfach, dass der Standard die Compilerhersteller
nicht zu stark in ihrem Optimierungspotenzial bremsen möchte und
ihnen so genügend Freiraum gibt, die einzelnen Teiloperationen
beliebig in der Reihenfolge anzordnen.

> Ich dachte die post inkrement operatoren werden nach dem
> Vergleich ausgeführt?

Genau das ist eben nicht festgelegt.  Es ist nur festgelegt, dass
der Vergleich den Wert von C von vor der Inkrementierung benutzen
muss, aber das sagt nichts darüber aus, ob C zu dem Zeitpunkt, da der
Vergleich stattfindet, bereits inkrementiert worden ist oder nicht.

: Bearbeitet durch Moderator
Autor: Günter X. (kolle)
Datum:

Bewertung
-3 lesenswert
nicht lesenswert
Also ich hab's mit gnu getestet und "A is A" (was auch zu erwarten war)

Allerdings habe ich den Fehler der fehlenden Initialisierung 
kompensiert, sowas macht kein ersthafter Programmiere.

Zudem steht in allmöglichen C Büchern die Auswirkung der Schreibweise 
++i oder i++

Wer das irgnoriert sollte sich nicht ärgern wenn er Stunden beim 
sinnlosen debuggen verplämpert oder Stress vom Chef bekommt.

Autor: Jörg W. (dl8dtl) (Moderator) Benutzerseite
Datum:

Bewertung
3 lesenswert
nicht lesenswert
Günter X. schrieb:
> Also ich hab's mit gnu getestet und "A is A" (was auch zu erwarten war)

Wieder einer, der noch nichts von diesem Thread verstanden hat. :-(

Autor: Daniel A. (daniel-a)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Günter X. schrieb:
> Also ich hab's mit gnu getestet und "A is A" (was auch zu erwarten war)

Ja und ich mit gcc (Gentoo 4.9.3 p1.4, pie-0.6.4) 4.9.3:
abd@basalt ~ $ gcc -x c -o ud -
#include <stdio.h>
#define print puts
void main (void) {
int C=0;
 if ( C++ == C++ ) {
  print ( "A is A\n" );
  } else {
  print ( "A is not A\n");
 }
}
abd@basalt ~ $ ./ud 
A is not A

abd@basalt ~ $

Undefined eben.

: Bearbeitet durch User
Autor: Dussel (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
freitagsposter schrieb:
> viel spass beim freitagsabtausch
Die erste Frage ist, welche Sprache das im Beispiel ist.
C oder C++ ist es wegen "void main" nicht, C# und Java haben meines 
Wissens kein print, Assembler, Fortran, Pascal, Cobol und so weiter ist 
es offensichtlich nicht…
Also vor der Diskussion über den Standard, erstmal die Diskussion über 
die Sprache. [Hier fehlt mir jetzt doch ein passendes Smiley.]

Autor: Frank M. (ukw) (Moderator) Benutzerseite
Datum:

Bewertung
1 lesenswert
nicht lesenswert
Daniel A. schrieb:
> Ja und ich mit gcc (Gentoo 4.9.3 p1.4, pie-0.6.4) 4.9.3:
> [...]
> A is not A

gcc 4.6.1: A is A
gcc 4.7.4: A is A
gcc 4.9.2: A is not A

Wir können ja eine Strichliste machen, wer rechter hat ;-)

Autor: Günter X. (kolle)
Datum:

Bewertung
-3 lesenswert
nicht lesenswert
Jörg W. schrieb:
> Es ist nur festgelegt, dass
> der Vergleich den Wert von C von vor der Inkrementierung benutzen
> muss, aber das sagt nichts darüber aus, ob C zu dem Zeitpunkt, da der
> Vergleich stattfindet, bereits inkrementiert worden ist oder nicht.

Der erste Teil beschreibt klar die Regel welche im zweiten Teil wieder 
in Frage gestellt wird. Der Satz als solches ist nicht logisch.


Ist das eine persönliche Interpretation oder gibt es für den Satz 
belastbare Beweise?

Autor: Vlad T. (vlad_tepesch)
Datum:

Bewertung
1 lesenswert
nicht lesenswert
Frank M. schrieb:
> gcc 4.6.1: A is A
> gcc 4.7.4: A is A
> gcc 4.9.2: A is not A

und jetzt bitte noch jerweils mit unterschiedlichen optimierungs 
optionen.
Und selbst wenn:
Das Verhalten ist undefined! sprich, wenn du zwei mal an verschiednen 
Stellen diese operation durchführst, muss nicht beide male das gleiche 
Ergebnis rauskommen. Das kann völlig davon abhängen, wie der Compiler 
den Code drum herum aufbaut.

Wäre es "Implementation Defined" müsste es sich immer gleich verhalten 
und dokumentiert sein, aber bei "undefined" ist es "Zufall"

Autor: Jörg W. (dl8dtl) (Moderator) Benutzerseite
Datum:

Bewertung
3 lesenswert
nicht lesenswert
Günter X. schrieb:
> Der Satz als solches ist nicht logisch.

Für dich vielleicht nicht, für mich schon.

Die ganze Thematik wurde doch nun ausreichend hier auf und nieder
gebetet.  Wenn du's immer noch nicht glaubst, die Drafts des
ISO-C-Standards kursieren frei im Internet.  Lies sie einfach.

Autor: Frank M. (ukw) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Vlad T. schrieb:
> und jetzt bitte noch jerweils mit unterschiedlichen optimierungs
> optionen.

Bringt nix.

> Und selbst wenn:
> Das Verhalten ist undefined! sprich, wenn du zwei mal an verschiednen
> Stellen diese operation durchführst, muss nicht beide male das gleiche
> Ergebnis rauskommen. Das kann völlig davon abhängen, wie der Compiler
> den Code drum herum aufbaut.

Vlad, ich weiß das. Ich wollte eigentlich nur darstellen, wie unsinnig 
eine Deutung des Ergebnisses ist. Deshalb schrieb ich "wer rechter hat".

Autor: Günter X. (kolle)
Datum:

Bewertung
-5 lesenswert
nicht lesenswert
Ich kann damit leben das C vor der Abfrage = 0 ist, "A is A" raus kommt 
und am Ende in C 2 zu finden ist, das ergibt Sinn.

Wer meint das anders sehen zu wollen kann das gerne machen.

Das ein solcher Konstrukt in der Praxis nicht wirklich vorkommt 
entschärft die Sache dann komplett :)

Autor: A. K. (prx)
Datum:

Bewertung
2 lesenswert
nicht lesenswert
Günter X. schrieb:
> Ist das eine persönliche Interpretation oder gibt es für den Satz
> belastbare Beweise?

Da das in den Standard selbst recht verschlüsselt ausgedrückt ist, hilft 
das C99 Rationale vom Standardisierungsgremium:

"The storage assignment need not take place until the next sequence 
point (*). As a consequence, a straightforward syntactic test for 
ambiguous expressions can be stated. Some definitions: A side effect is 
a storage to any data object [...]. An ambiguous expression is one whose 
value depends upon the order in which side effects are evaluated. [...].

We can then say that an unsequenced expression may be ambiguous [...] if 
more than one operand contains an lvalue referencing the same object and 
one or more operands specify a side-effect to that object."

Der Fall ist hier gegeben.

*: Gibts innerhalb von "C++ == C++" nicht. Appendix C in C99/C11.

: Bearbeitet durch User
Autor: A. K. (prx)
Datum:

Bewertung
1 lesenswert
nicht lesenswert
PS: Es ist nicht nur offen, welcher Zweig ausgeführt wird. Es ist auch 
offen, ob C hinterher um 2 oder um 1 grösser ist.

Man erhält bei "C++ == C++" beispielhaft drei Abläufe:
  (1) load T1, copy, increment, store - vom linken C++
  (2) load T2, copy, increment, store - vom rechten C++
  (3) compare T1 and T2
(nochmal: das ist nur ein Beispiel für mögliche Abläufe).

Festgelegt ist hier nur, dass (3) nach dem Load in (1) und (2) 
stattfindet. Ansonsten darf der Compiler die Teiloperationen der 3 
Abläufe beliebig ineinander verzahnen.

: Bearbeitet durch User
Autor: freitagsposter (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert

 void main (void) {
 
  int C;
 
  if ( C++ == C-- ) {
   print ( "A is A\n" );
   } else {
   print ( "A is not A\n");
  }
 }


Autor: freitagsposter (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
void main (void) {

   int C;

   if ( C++ == --C ) {
    print ( "A is A\n" );
    } else {
    print ( "A is not A\n" );
   }
  }

Autor: Jörg W. (dl8dtl) (Moderator) Benutzerseite
Datum:

Bewertung
1 lesenswert
nicht lesenswert
Egal, wie viele Varianten du dir davon ausdenkst: sie erzeugen alle
undefiniertes Verhalten.

Noch was: keiner zwingt dich, beim Absenden deiner Postings eine
Mailadresse einzutragen.  Wenn du dich aber schon entscheidest, eine
einzutragen, dann bitte eine, unter der dich die Forensoftware auch
erreichen kann.  Durch Angabe einer nicht existierenden Adresse
outest du dich einfach nur als Troll.

Autor: fürn Hugo (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
bei meinen Compiler kommt:

Error, integer not initialized!
12:   int C;

heraus?

Autor: A. K. (prx)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Um das ein wenig auf die Spitze zu treiben - Du kannst mir doch sicher 
sagen, was hier rauskommen sollte:
int f(void)
{
        int x;
        return (x = 1) + (x = 2);
}

: Bearbeitet durch User
Autor: freitagsposter (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Jörg W. schrieb:
> Egal, wie viele Varianten du dir davon ausdenkst: sie erzeugen
> alle
> undefiniertes Verhalten.

dann definier sie dir doch,
es kommt das "selbe" ergebnis hervor.

>
> Noch was: keiner zwingt dich, beim Absenden deiner Postings eine
> Mailadresse einzutragen.  Wenn du dich aber schon entscheidest, eine
> einzutragen, dann bitte eine, unter der dich die Forensoftware auch
> erreichen kann.  Durch Angabe einer nicht existierenden Adresse
> outest du dich einfach nur als Troll.

du kennst doch meine email addresse

;-)

Autor: freitagsposter (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
A. K. schrieb:
> Um das ein wenig auf die Spitze zu treiben - Du kannst mir doch
> sicher
> sagen, was hier rauskommen sollte:

sollte 3
tun 4

Autor: A. K. (prx)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Und was sagt dir das?

Autor: freitagsposter (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Jörg W. schrieb:
> Günter X. schrieb:
>> Der Satz als solches ist nicht logisch.
>
> Für dich vielleicht nicht, für mich schon.

für mich auch aber ich verstehe dein "aufkochen" an dem thread nicht 
jörg.

es sollte eine "denksportaufgabe" sein, nichts weiter.
dass jemand hier tatsächlich ein undefiniertes verhalten nachrechnet,
wäre mir nie in den sinn. es geht um die feststellung, dass dies nicht 
im standard definiert ist.

undefiniertes "verhalten"

;-)

Autor: Andreas B. (andreas_b77)
Datum:

Bewertung
2 lesenswert
nicht lesenswert
Sobald undefiniertes Verhalten ins Spiel kommt gibt es keine falschen 
Antworten mehr. Als "Denksport" ist das nicht sehr herausfordernd.

Autor: A. K. (prx)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
freitagsposter schrieb:
> dass jemand hier tatsächlich ein undefiniertes verhalten nachrechnet,
> wäre mir nie in den sinn. es geht um die feststellung, dass dies nicht
> im standard definiert ist.

Du wolltest also nur feststellen, dass undefiniertes Verhalten nicht 
definiert ist?

Autor: Rolf M. (rmagnus)
Datum:

Bewertung
1 lesenswert
nicht lesenswert
Andreas B. schrieb:
> Sobald undefiniertes Verhalten ins Spiel kommt gibt es keine falschen
> Antworten mehr. Als "Denksport" ist das nicht sehr herausfordernd.

Wie ich ja schon vor über einer Woche in 
Beitrag "Re: * C++ == C++ *" geschrieben habe. 
Interessant, dass hier immer noch darüber diskutiert wird. Aber 
scheinbar ist es für manche doch mit einer größeren gedanklichen 
Anstrengung verbunden, zu erkennen, was undefiniert bedeutet.

Autor: Draco (Gast)
Datum:

Bewertung
4 lesenswert
nicht lesenswert
Rolf M. schrieb:
> Aber scheinbar ist es für manche doch mit einer größeren gedanklichen
> Anstrengung verbunden, zu erkennen, was undefiniert bedeutet.

Ach für mich ist "undefiniertes Verhalten" ganz einfach, ich sehe das 
jeden Morgen: ab dem Zeitpunkt wenn meine Frau aufsteht bis zu ihrem 
ersten Kaffee ist das alles "undefiniertes Verhalten". Da lass ich auch 
lieber meine Finger davon. ;-)

Autor: Peter D. (peda)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Es ist doch alles ganz einfach:
Wird ein Ausdruck auf der linken Seite modifiziert, darf vor einem 
sequence point nicht ein weiteres mal davon gelesen werden.
Der Compiler warnt einen dann:
  j = i++ + i;
test.c:6: warning: operation on 'i' may be undefined
Erlaubt ist z.B.:
  j = i++ ? ++i : 10;

Autor: Jörg W. (dl8dtl) (Moderator) Benutzerseite
Datum:

Bewertung
1 lesenswert
nicht lesenswert
Peter D. schrieb:

> Erlaubt ist z.B.:
>
>   j = i++ ? ++i : 10;
> 

Ist aber schon fast IOCCC-verdächtig. ;-)

Autor: Fritz G. (fritzg)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Für die Strichliste:

A is not A

Apple LLVM version 8.0.0 (clang-800.0.38)

Autor: Dussel (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Fritz G. schrieb:
> Für die Strichliste:
>
> A is not A
Interessant wäre, wo was ganz anderes rauskommt.

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.