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


von freitagsposter (Gast)


Lesenswert?

@mod bitte verschieben wenn unpassendes forum "code"


viel spass beim freitagsabtausch



1
void main (void) {
2
3
 int C;
4
5
 if ( C++ == C++ ) {
6
  print ( "A is A\n" );
7
  } else {
8
  print ( "A is not A\n");
9
 }
10
}

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


Lesenswert?

A is not A

von Yalu X. (yalu) (Moderator)


Lesenswert?

Da meckert schon der Compiler bzw. Linker:
1
implicit declaration of function ‘print’
2
3
undefined reference to `print'

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

Selbst wenn man C intialisiert, meckert der Compiler:
1
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:
1
warning: multiple unsequenced modifications to 'C' [-Wunsequenced]
2
  if ( C++ == C++ ) {
3
        ^      ~~

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

: Bearbeitet durch Moderator
von Maximilian S. (maxst)


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

von Peter II (Gast)


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)

von C-Kenner (Gast)


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.

von Yalu X. (yalu) (Moderator)


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.

von freitagsposter (Gast)


Lesenswert?

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

1
int main( int c, char *v[]) {
2
 
3
  struct {
4
   unsigned long x : 33;
5
  } s;
6
7
  typedef typeof(0+s.x) uint33;
8
  
9
  uint33 y = -1;
10
  
11
  printf("%lu\n\n", (unsigned long)y);
12
  
13
  uint33 t[3] = { 0x100000000 };
14
  t[1] = t[0] + 1;
15
  t[2] = t[0] + t[1];
16
  
17
  for (int i = 0; i<3; i++)
18
    printf("%9lx\n", (unsigned long)t[i]);
19
  
20
}

gcc t.c && ./a.outp

??

von freitagsposter (Gast)


Lesenswert?

alles ist möglich!

von freitagsposter (Gast)


Lesenswert?

sicher den rechtschreibpatzer bemerkt aber vorsichtshalber:

das 'p' am ende war zuviel


gcc t.c && ./a.out


??

von freitagsposter (Gast)


Lesenswert?

8589934591

100000000
100000001
        1


;-)

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

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

Außerdem hast Du ein

#include <stdio.h>

vergessen ;-)

: Bearbeitet durch Moderator
von freitagsposter (Gast)


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

von freitagsposter (Gast)


Lesenswert?

das wäre die richtige antwort

;-)

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

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

Bewahrt mich aber auch vor Unsinn ;-)

von freitagsposter (Gast)


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 ;-)

von Daniel A. (daniel-a)


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 ;)

von freitagsposter (Gast)


Lesenswert?

Frank M. schrieb:
> t.c: In function 'main':
> t.c:6:4: error: width of 'x' exceeds its type
> ...
1
.LC0:
2
        .string "%lu %lu\n\n"
3
.LC1:
4
        .string "%9lx\n"
5
main:
6
        subq    $8, %rsp
7
        movabsq $8589934590, %rdx
8
        movabsq $8589934591, %rsi
9
        movl    $.LC0, %edi
10
        xorl    %eax, %eax
11
        call    printf
12
        movabsq $4294967296, %rsi
13
        movl    $.LC1, %edi
14
        xorl    %eax, %eax
15
        call    printf
16
        movabsq $4294967297, %rsi
17
        movl    $.LC1, %edi
18
        xorl    %eax, %eax
19
        call    printf
20
        movl    $1, %esi
21
        movl    $.LC1, %edi
22
        xorl    %eax, %eax
23
        call    printf
24
        xorl    %eax, %eax
25
        addq    $8, %rsp
26
        ret

x86-64 gcc 6.1
-xc -O2

von freitagsposter (Gast)


Lesenswert?

und jetzt?
1
// dont forget this!!
2
// ;-)
3
#include <stdio.h>
4
5
int main(int c, char *v[])
6
{
7
  struct {
8
    unsigned long x : 33;
9
  } s;
10
11
  typedef typeof(0+s.x) uint33;
12
13
  uint33 y = -1;
14
15
  printf("%lu %lu\n\n", (unsigned long)y, (unsigned long)(y + y));
16
17
  uint33 t[3] = { 0x100000000 };
18
  t[1] = t[0] + 1;
19
  t[2] = t[0] + t[1];
20
21
  for (int i = 0; i<3; i++)
22
    printf("%9lx\n", (unsigned long)t[i]);
23
  
24
}

von steinadler (Gast)


Lesenswert?

VS2012 C# kompiliert das ohne Probleme bzw. Warnung.

Natürlich "A is not A"

von steinadler (Gast)


Lesenswert?

1
            int c = 5;
2
            int pascal = 5;
3
4
            if (c++ == pascal)
5
            {
6
print ( "C++ is Pascal\n" );
7
            }
8
            else
9
            {
10
print ( "C++ is not Pascal\n" );
11
            }

Ist auch interessant ;-)

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


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/

von Yalu X. (yalu) (Moderator)


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

1
#include <stdio.h>
2
3
int main(void) {
4
 
5
  struct {
6
   unsigned long x : 33;
7
  } s = { 0x1ffffffff };
8
9
  printf("%9lx\n", (unsigned long)s.x);
10
  printf("%9lx\n", (unsigned long)(s.x + 1));
11
  printf("%9lx\n", (unsigned long)(2*s.x));
12
}

liefert mit dem GCC:

1
1ffffffff
2
        0
3
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:

1
1ffffffff
2
200000000
3
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.

von Rolf M. (rmagnus)


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. ;-)

von Günter X. (kolle)


Lesenswert?

Joachim D. schrieb:
> A is not A

Öhm nöö.

A is A

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

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


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).

von Yalu X. (yalu) (Moderator)


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.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

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

Stimmt auch wieder.

von dulnik (Gast)


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".

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

dulnik schrieb:
> Die Antwort lautet daher "A is A".

Noch einer, der's nicht kapieren will …

von Yalu X. (yalu) (Moderator)


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 :)

von Bernd K. (prof7bit)


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
von Mano W. (Firma: ---) (manow)


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...

von Bernd K. (prof7bit)


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?

von dulnik (Gast)


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?

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


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
von Günter X. (kolle)


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.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


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. :-(

von Daniel A. (daniel-a)


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:
1
abd@basalt ~ $ gcc -x c -o ud -
2
#include <stdio.h>
3
#define print puts
4
void main (void) {
5
int C=0;
6
 if ( C++ == C++ ) {
7
  print ( "A is A\n" );
8
  } else {
9
  print ( "A is not A\n");
10
 }
11
}
12
abd@basalt ~ $ ./ud 
13
A is not A
14
15
abd@basalt ~ $

Undefined eben.

: Bearbeitet durch User
von Dussel (Gast)


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.]

von Frank M. (ukw) (Moderator) Benutzerseite


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 ;-)

von Günter X. (kolle)


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?

von Vlad T. (vlad_tepesch)


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"

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


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.

von Frank M. (ukw) (Moderator) Benutzerseite


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".

von Günter X. (kolle)


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 :)

von (prx) A. K. (prx)


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
von (prx) A. K. (prx)


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
von freitagsposter (Gast)


Lesenswert?

1
 void main (void) {
2
 
3
  int C;
4
 
5
  if ( C++ == C-- ) {
6
   print ( "A is A\n" );
7
   } else {
8
   print ( "A is not A\n");
9
  }
10
 }

von freitagsposter (Gast)


Lesenswert?

void main (void) {

   int C;

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

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


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.

von fürn Hugo (Gast)


Lesenswert?

bei meinen Compiler kommt:

Error, integer not initialized!
12:   int C;

heraus?

von (prx) A. K. (prx)


Lesenswert?

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

: Bearbeitet durch User
von freitagsposter (Gast)


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

;-)

von freitagsposter (Gast)


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

von (prx) A. K. (prx)


Lesenswert?

Und was sagt dir das?

von freitagsposter (Gast)


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"

;-)

von Andreas B. (andreas_b77)


Lesenswert?

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

von (prx) A. K. (prx)


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?

von Rolf M. (rmagnus)


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.

von Draco (Gast)


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. ;-)

von Peter D. (peda)


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:
1
  j = i++ + i;
test.c:6: warning: operation on 'i' may be undefined
Erlaubt ist z.B.:
1
  j = i++ ? ++i : 10;

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Peter D. schrieb:

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

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

von Fritz G. (fritzg)


Lesenswert?

Für die Strichliste:

A is not A

Apple LLVM version 8.0.0 (clang-800.0.38)

von Dussel (Gast)


Lesenswert?

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

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.