ARM-GCC versteht den Witz nicht.

OP #6748674
Lesenswert?

Hallo zusammen,

aus Langeweile habe ich mal einen gerade kursierenden Witz 
ausprobiert/implementiert:
1
volatile int a = "100" + 2 == "0"
(das Ganze in einer ansonsten nackten main() und mit dem Debugger das 
Ergebnis auf einem STM32F103C8RB angeschaut.)

ARM-GCC 5.4.1  -O3: a ist false
ARM-GCC 5.4.1  -Os: a ist true

Aber nicht nur das. Es wird für den Ausdruck auf der rechten Seite 
tatsächlich Code generiert:
1
(32)      volatile int isInterleaved = "100"+2 == "0";
2
08000282  ldr  r3, [pc, #16]  ; (0x8000294 <main+20>)
3
08000284  ldr  r2, [pc, #16]  ; (0x8000298 <main+24>)
4
08000286  subs  r2, r3, r2
5
08000288  negs  r3, r2
6
0800028A  adcs  r3, r2
7
0800028C  str  r3, [sp, #4]

Das erzeugt zwei Fragen:
 a) Warum spart sich der Compiler das Schachteln der Zeichenketten in 
-O3? Ich kann durch das Schachteln keine Strafe auf die Geschwindigkeit 
erkennen.
 b) Warum kann der Compiler den konstanten Ausdruck auf der rechten 
Seite nicht auswerten und wegoptimieren? Zumindest bei -Os hat er doch 
erkannt, dass die Differenz immer 4 ist?
Beitrag #6748676 wurde von einem Moderator gelöscht.
Gast #6748678
Lesenswert?

Walter T. schrieb:
> Das erzeugt zwei Fragen:
>  a) Warum spart sich der Compiler das Schachteln der Zeichenketten in
> -O3? Ich kann durch das Schachteln keine Strafe auf die Geschwindigkeit
> erkennen.
>  b) Warum kann der Compiler den konstanten Ausdruck auf der rechten
> Seite nicht auswerten und wegoptimieren? Zumindest bei -Os hat er doch
> erkannt, dass die Differenz immer 4 ist?

Die für mich relevante Frage samt Antwort fehlt. Was erwartest du als 
Ergebnis?
#6748681
Lesenswert?

Wie kommst Du darauf, das die Differenz "4" ist? Du addierst auf einen 
(const char) Pointer "100" den Wert 2 und vergleichst diesen neuen 
Pointer mit einem weiteren Pointer.

Bei "-Os" macht der Compiler vermutlich einen String Merge von "100" und 
"0": Es reicht "100" im Code zu hinterlegen, man kann "0" als Substring 
darstellen.
Gast #6748688
Lesenswert?

Walter T. schrieb:
>> Was erwartest du als Ergebnis?

> "Implementation defined behaviour"

Bitte konkreter: was erwartest, und warum? Was wäre denn für dich in 
diesem Fall "defined behaviour" oder (wenn es keine solche Definition 
gibt) wie würdest du das Soll-Verhalten definieren wollen?

Meiner Meinung nach ist die Codezeile sinnloser Bullshit den keine Regel 
von C beschreibt.
Beitrag #6748702 wurde von einem Moderator gelöscht.
Gast #6748743
Lesenswert?

> Das erzeugt zwei Fragen:
> a) Warum spart sich der Compiler das Schachteln der Zeichenketten in
> -O3? Ich kann durch das Schachteln keine Strafe auf die Geschwindigkeit
> erkennen.

Der String ist nicht mehr aligned und Zugriffe drauf evtl langsamer.

> b) Warum kann der Compiler den konstanten Ausdruck auf der rechten
> Seite nicht auswerten und wegoptimieren? Zumindest bei -Os hat er doch
> erkannt, dass die Differenz immer 4 ist?

Bei zwei unabhängigen Strings vergibt erst der Linker die Adressen.
Gast #6748787
Lesenswert?

foobar schrieb:
> Bei zwei unabhängigen Strings vergibt erst der Linker die Adressen.
Die Strings sind nicht zwingend "unabhängig". Der Compiler/Linker darf 
die letzte das Ende von "100" als "0" benutzen. Das ist das unspecified 
Verhalten, dass hier schon genannt wurde. Wenn der Compiler/Linker das 
nicht macht, ist das Verhalten undefined, weil die beiden Pointer nicht 
in das selbe Objekt (Array-of-char) zeigen.
Gast #6748791
Lesenswert?

Andreas M. schrieb:
> Wie kommst Du darauf, das die Differenz "4"

Tippfehler. Das Listing hatte mich irritiert.

foobar schrieb:
> Der String ist nicht mehr aligned und Zugriffe drauf evtl langsamer.

Das klingt plausibel.

foobar schrieb:
> Bei zwei unabhängigen Strings vergibt erst der Linker die Adressen.

Das auf den ersten Blick nicht: Wenn der Compiler die Strings 
schachtelt, ist die Bedingung immer erfüllt, egal wie der Linker ihn 
schiebt. Wenn nicht, nie. Aber okay. Der Compiler hat in der abstrakten 
Maschine nichts mit den Adressen zu schaffen.

Ob LTO etwas an der Situation ändert?
OP #6748810
Lesenswert?

Stefan ⛄ F. schrieb:
> Meiner Meinung nach ist die Codezeile sinnloser Bullshit den keine Regel
> von C beschreibt.

Ich kenne keine Regel, die diese Zeile verbietet. Aber ich bin nur 
Hobbyist und lerne gern dazu.


mh schrieb:
> Der gcc mit Wall sagt undefined.

Meiner sagt übrigens "unspecified behavior", also der schmale Grat 
zwischen implementation defined und undefined, auf dem ich gefühlt noch 
nie zuvor spaziert bin.


mh schrieb:
> Wenn der Compiler/Linker das
> nicht macht, ist das Verhalten undefined, weil die beiden Pointer nicht
> in das selbe Objekt (Array-of-char) zeigen.

Ich kenne keine Regel, die den Vergleich beliebiger Zeiger auf 
unterschiedliche Arrays verbietet.


Walter Tarpan (Gast) schrieb:
> Ob LTO etwas an der Situation ändert?

Die Frage fand ich dann doch noch interessant genug, den PC noch einmal 
zu starten. Bei LTO ergibt sich kein Unterschied. -O3 und -Os haben 
immer noch jeweils das zuvor beschriebene Verhalten in Bezug auf das 
jeweilige Ergebnis (true|false).

Aaber: Die rechte Seite wird jetzt komplett wegoptimiert, und jeweils 
der Wert als Immediate direkt geladen.
Gast #6748824
Lesenswert?

Walter T. schrieb:
> mh schrieb:
>> Der gcc mit Wall sagt undefined.
>
> Meiner sagt übrigens "unspecified behavior", also der schmale Grat
> zwischen implementation defined und undefined, auf dem ich gefühlt noch
> nie zuvor spaziert bin.

Ja er sagt unspecified, ich habe gelesen, was ich erwartet habe. Und 
implementation defined ist nochmal was anderes. Es ist unspecified, weil 
der Compiler die Strings zusammenlegen darf, wenn es möglich ist. Er 
muss er muss aber nicht dokumentieren, ob oder wann er es macht. Wenn er 
es dokumentieren müsste, wäre es implementation defined. Undefined wird 
es, weil Pointer auf unterschiedliche Objekte verglichen werden, wenn er 
sie nicht zusammen legt.
Da du dir aber nicht sicher sein kannst welches Verhalten gerade 
zutrifft, ist es effektiv immer undefined.

Walter T. schrieb:
> mh schrieb:
>> Wenn der Compiler/Linker das
>> nicht macht, ist das Verhalten undefined, weil die beiden Pointer nicht
>> in das selbe Objekt (Array-of-char) zeigen.
> Ich kenne keine Regel, die den Vergleich beliebiger Zeiger auf
> unterschiedliche Arrays verbietet.
1
6.5.8 Relational operators
2
...
3
5) When two pointers are compared, the result depends on the relative locations in the address space
4
of the objects pointed to. If two pointers to object types both point to the same object, or both point
5
one past the last element of the same array object, they compare equal. If the objects pointed to are
6
members of the same aggregate object, pointers to structure members declared later compare greater
7
than pointers to members declared earlier in the structure, and pointers to array elements with larger
8
subscript values compare greater than pointers to elements of the same array with lower subscript
9
values. All pointers to members of the same union object compare equal. If the expression P points
10
to an element of an array object and the expression Q points to the last element of the same array
11
object, the pointer expression Q+1 compares greater than P. In all other cases, the behavior is undefined.
Gast #6748828
Lesenswert?

Walter T. schrieb:
> Ich kenne keine Regel, die diese Zeile verbietet.

Die Zeile ist nicht verboten. Aber sie enthält einige Konstrukte, die 
vielleicht anders sind als Du erwartest und die deshalb vielleicht 
andere Ergebnisse liefern als Du erwartest.

Darum die Frage, was Du erwartest.

Dass verschiedene Dinge rauskommen, liegt daran, dass der Compiler frei 
ist, das zu implementieren, wie er will.

Also ganz ehrlich, verstehst Du, wann genau true rauskommt und wann 
genau nicht?
OP #6748846
Lesenswert?

mh schrieb:
> Da du dir aber nicht sicher sein kannst welches Verhalten gerade
> zutrifft, ist es effektiv immer undefined.

Naja, für mich gibt es zwischen "undefined" und "unspecified" einen 
heftigen Unterschied: Bei "undefined" macht der Compiler ein lautes 
"Ätsch, jetzt bringe ich Dir alle anderen Sachen auch noch 
durcheinander! Ich darf das!", bei "unspecified" steht in einer Variable 
ein falscher/unerwarteter Wert.

Aber ich bin jetzt etwas irritiert:
1
int a, b, *ap, *bp;
2
ap = &a, bp = &b; 
3
int c = *ap == *bp;
Definiert oder nicht definiert?

Wenn ich mir den Absatz noch einmal in Ruhe durchlesen, würde ich 
ersteres sagen. Und c ist immer 0.
#6748850
Lesenswert?

Sebastian schrieb:
>> 6.5.8.5 ... "In all other cases, the behavior is undefined."
>
> Das gilt für relationale Operatoren. Pointergleichheit wird in 6.5.9,
> inbesonders 6.5.9.6 spezifiziert. Zwei Pointer auf unterschiedliche
> Speicherbereiche sind ungleich, nicht undefiniert.

Da 6.5.9.3 Vergleiche auf Gleichheit auf relationale Vergleiche 
zurückführt, gelten folglich die Regeln aus 6.5.8 analog.
Gast #6748851
Lesenswert?

Walter T. schrieb:
> Das erzeugt zwei Fragen:
>  a) Warum spart sich der Compiler das Schachteln der Zeichenketten in
> -O3? Ich kann durch das Schachteln keine Strafe auf die Geschwindigkeit
> erkennen.
Wozu? Die Strings fallen doch weg, er braucht sie nicht anlegen. Der 
restliche Code kann sie ja eh nicht "fassen".
>  b) Warum kann der Compiler den konstanten Ausdruck auf der rechten
> Seite nicht auswerten und wegoptimieren? Zumindest bei -Os hat er doch
> erkannt, dass die Differenz immer 4 ist?
Ist der erstellte Code in beiden gleich? Ggf. weil der Linker ja erst 
die Adressen liefert ;-)
Gast #6748854
Lesenswert?

Walter T. schrieb:
> Aber ich bin jetzt etwas irritiert:
> int a, b, *ap, *bp;
> ap = &a, bp = &b;
> int c = *ap == *bp;
> Definiert oder nicht definiert?
>
> Wenn ich mir den Absatz noch einmal in Ruhe durchlesen, würde ich
> ersteres sagen. Und c ist immer 0.
Definiert, klar. Warum nicht. Aber warum 0? was in a oder b steht ist 
doch völlig unbekannt. Die können gleich sein, müssen aber nicht.
OP #6748856
Lesenswert?

(prx) A. K. schrieb:
> Es geht dabei nicht um
> Pointer auf verschiedene Objekte.

Genau. Also würde ich den Satz "In all other cases, the behavior is 
undefined." explizit auf den Vergleich zweier Zeiger auf das gleiche 
Array beziehen. Das steht deshalb da, weil die Regel für Zeiger hier 
etwas aufgeweicht sind, weil ein Element über das Array hinaus gezeigt 
werden darf.

Oben: Tippfehler. Gemeint ist natürlich
1
int a, b, *ap, *bp;
2
ap = &a, bp = &b; 
3
int c = ap == bp;

Bin zwar nicht so schnippisch wie ein Compiler, werde aber dafür 
schneller müde.
Moderator Persönliche Seite #6748860
Lesenswert?

Sebastian schrieb:
> Zwei Pointer auf unterschiedliche Speicherbereiche sind ungleich, nicht
> undefiniert.

Es ist aber nicht sicher, ob es sich um unterschiedliche 
Speicherbereiche handelt oder nicht. Diese Auswahl ist dem Compiler 
freigestellt.

6.4.5 (in meinem Draft, den ich gerade habe ;), steht aber schon lange 
so drin)

String literals

"It is unspecified whether these arrays are distinct provided their 
elements have the appropriate values. If the program attempts to modify 
such an array, the behavior is undefined."

Damit ist das Verhalten hier "unspecified", und es ist völlig plausibel, 
dass abhängig von der gewählten Optimierung unterschiedliche Ergebnisse 
produziert werden.
#6748862
Lesenswert?

Dieses Loch des C Standards C wurde in C++ explizit gestopft. 5.10: 
"Pointers of the same type (after pointer conversions) can be compared 
for equality. Two pointers of the same type compare equal if and only if 
they are both null, both point to the same function, or both represent 
the same address (3.9.2)"

Für C könnte man auch sagen, dass das Verhalten schon deshalb 
undefiniert ist, weil der Standard es weder als klar definiert noch als 
klar undefiniert definiert. ;-)
Moderator Persönliche Seite #6748870
Lesenswert?

(prx) A. K. schrieb:
> Dieses Loch des C Standards C wurde in C++ explizit gestopft.

An der Stelle nicht wirklich: die Frage ist ja, ob sie im obigen 
Beispiel auch tatsächlich auf die gleiche Adresse zeigen oder nicht. Es 
würde mich wundern, wenn der C++-Standard an dieser Stelle expliziter 
wäre und entweder das Zusammenlegen oder das Verteilen der beiden den 
Strings zugrundeliegenden Arrays vorschriebe.
Gast #6748871
Lesenswert?

Walter T. schrieb:
> Oben: Tippfehler. Gemeint ist natürlichint a, b, *ap, *bp;
> ap = &a, bp = &b;
> int c = ap == bp;

a und b sind doch in jedem Fall unterschiedliche Adressen. Also ja, 0, 
ungleich.

Beim String-Beispiel ist es ja eher so, dass Du zwei "zufällige" 
Adressen hast, die je nach Laune gleich oder ungleich sein können.

Da strings auch nicht unterschiedlich sein können, wenn sie den gleichen 
Anfang haben, ist das auch kein praktisches Problem.

Entweder sind strings (die Adressen) gleich, dann ist auch der Text 
gleich. Oder sie sind es nicht, dann ist der Text beliebig. Meist 
unterschiedlich, kann aber trotzdem gleich sein.
#6748874
Lesenswert?

Zwischen den Zeilen gelesen ist ein Vergleich auf Gleichheit auch in C 
definiert: "Two pointers compare equal if and only if [...] one is a 
pointer to one past the end of one array object and the other is a 
pointer to the start of a different array object that happens to 
immediately follow the first array object in the address space."
#6748876
Lesenswert?

Walter T. schrieb:
> Genau. Also würde ich den Satz "In all other cases, the behavior is
> undefined." explizit auf den Vergleich zweier Zeiger auf das gleiche
> Array beziehen.

Nein. Der Text ist da sehr eindeutig.

Da steht eine Aufzählung aller zugelassenen Vergleiche, und an deren 
Ende, daß alle anderen Fälle undefined sind. Da gibts wenig dran zu 
deuteln.

Oliver
#6748887
Lesenswert?

Jörg W. schrieb:
> (prx) A. K. schrieb:
>> Dieses Loch des C Standards C wurde in C++ explizit gestopft.
>
> An der Stelle nicht wirklich: die Frage ist ja, ob sie im obigen
> Beispiel auch tatsächlich auf die gleiche Adresse zeigen oder nicht.

Mit dem Loch meinte ich die klare Festlegung im Standard, ob Vergleiche 
auf Identität von Pointern auf verschiedene Objekte zulässig sind. Ich 
würde nun sagen, dass sie es auch in C sind. Nicht festgelegt ist damit 
aber, das Vergleiche auf verschiedene Objekte notwendigerweise auf 
"ungleich" entscheiden.
Gast #6748890
Lesenswert?

(prx) A. K. schrieb:
> Für C könnte man auch sagen, dass das Verhalten schon deshalb
> undefiniert ist, weil der Standard es weder als klar definiert noch als
> klar undefiniert definiert. ;-)

Das gilt aber nur, wenn Du

(prx) A. K. schrieb:
> 6.5.9.3: "The == (equal to) and != (not equal to) operators are
> analogous to the relational operators except for their lower
> precedence."

auf eine Eigenschaft beziehst, die nicht zwingend mitgemeint sein muss.

Es gibt ja so ein analogon bei % und / mit negativen Zahlen bei int. 
Egal wie mans macht, am Ende muss es Konsistent sein. Und bei > bzw. < 
auch: Egal was raus kommt, am Ende muss es (bei ungleichen Pointern) > 
oder < sein, um ein == zu erkennen. Und das ist so offensichtlich, dass 
es keiner expliziten Erklärung bedarf, die Hälfte aller 
Pointer-Vergleiche wäre sonst sinnlos.
#6748897
Lesenswert?

Das Problem könnte sein, dass für die Zeichenkette "100" zur 
Kompilierzeit noch keine Adresse feststeht, da diese erst beim Linken 
gebildet wird. Daher muss der Algorithmus diese Adresse zur Laufzeit 
berechnen. Damit muss auch der restliche Ausdruck zur Laufzeit berechnet 
werden.
Moderator Persönliche Seite #6748901
Lesenswert?

Gerald K. schrieb:
> Das Problem könnte sein, dass für die Zeichenkette "100" zur
> Kompilierzeit noch keine Adresse feststeht, da diese erst beim Linken
> gebildet wird.

Je nachdem eben. Es ist dem Compiler völlig freigestellt, ob er das 
bereits beim Compilieren zusammenwürfelt (möglich ist es ja) oder nicht.

Daher "unspecified". Es ist nicht "undefined", d.h. der Compiler kann 
sich eine von beiden Varianten aussuchen (die Zeiger sind gleich oder 
nicht), aber das Ergebnis darf nicht etwas ganz was anderes tun.
Gast #6748924
Lesenswert?

A. S. schrieb:
> Egal was raus kommt, am Ende muss es (bei ungleichen Pointern) > oder <
> sein

Ja, aber welches von beiden kann undefined sein. Und bei zwei Zeigern 
auf unterschiedliche Variablen ist eben Ungleichheit garantiert, aber 
nicht welcher Zeiger der Grössere ist.

Die Operatoren == und != sind eben nicht relational operators nach 6.5.8 
(das sind <, >, <= und >=) sondern equality operators nach 6.5.9.

LG, Sebastian
#6748925
Lesenswert?

Walter T. schrieb:
> Oliver S. schrieb:
>> Da steht eine Aufzählung aller zugelassenen Vergleiche, und an deren
>> Ende, daß alle anderen Fälle undefined sind. Da gibts wenig dran zu
>> deuteln.
>
> Dann wäre allerdings der Vergleich a == NULL auch undefined.

Nein. Der Abschnitt behandelt ausdrücklich den Vergleich von zwei 
Pointern, nicht den Test von einem Pointer auf Null.

Oliver
#6748944
Lesenswert?

Jörg W. schrieb:
> Trotzdem darf er "0\0" auf das Ende von "100\0" zeigen lassen, aber er
> muss nicht. Um nicht mehr und nicht weniger geht es im initialen
> Beispiel.

 **Einverstanden**

"0\0" ist ein Teil von "100\0".  Es könnte die gleiche Zeichenkette 
"100\0" verwendet werden.
Für "0\0" ist die Adresse um zwei größer, falls die Optimierung dies so 
umsetzt. Der absolute Wert kürzt sich heraus.
Beitrag #6748957 wurde von einem Moderator gelöscht.
Gast #6748972
Lesenswert?

Jemand schrieb:
> `a` und `b` enthalten indeterminate values, dürfen also eine /trap
> representation/ enthalten, der Zugriff darauf wäre undefined behavior.

Ich kenne mich da nicht aus. Ich hätte gedacht, es wäre bei int (@C11) 
ein "unspecified value".

1
3.19.2 indeterminate value
2
either an unspecified value or a trap representation
3
3.19.3 unspecified value
4
valid value of the relevant type where this International Standard imposes no
5
requirements on which value is chosen in any instance
6
2 NOTE An unspecified value cannot be a trap representation.
7
3.19.4 trap representation
8
an object representation that need not represent a value of the object type
Gast #6748988
Lesenswert?

(prx) A. K. schrieb:

> Der C Standard kennt eine. Ein Vergleich zwischen Pointern auf
> verschiedene Arrays ist undefiniert. 6.5.8.5 ... "In all other cases,
> the behavior is undefined."

Wenn der zweite String nicht reingefaltet wird UND direkt nach dem 
ersten String liegt, wäre der zweite Pointer aus Sicht des ersten 
Strings so ein "q+1".

Wenn der Compiler nicht reinfaltet, kann er zur Compile-Zeit nicht 
wissen, wo die Adressen liegen werden, kann also nicht mit Sicherheit 
sagen, ob es noch q+1 sein wird oder nicht. Er darf aber q+1 annehmen, 
weil das Gegenteil undefined behaviour wäre, so daß er für den letzteren 
Fall keinen Code generieren muß.
Gast #6748995
Lesenswert?

(prx) A. K. schrieb:
> Mit dem Loch meinte ich die klare Festlegung im Standard, ob Vergleiche
> auf Identität von Pointern auf verschiedene Objekte zulässig sind.

Gratuliere! Das erfordert schon eine große Menge an echter 
Abgezogenheit, wenn im Standard steht
[code]
Two pointers compare equal if ...  both are pointers to the same object 
...
[/code
dann noch zu denken, wenn das nicht der Fall ist, wäre nicht der 
Vergleich false, sondern das Verhalten undefiniert.
Echt, Gratuliere!
Moderator Persönliche Seite #6749044
Lesenswert?

Gerald K. schrieb:

> "0\0" ist ein Teil von "100\0".  Es könnte die gleiche Zeichenkette
> "100\0" verwendet werden.
> Für "0\0" ist die Adresse um zwei größer, falls die Optimierung dies so
> umsetzt. Der absolute Wert kürzt sich heraus.

Yep, genau darum dreht sich das initiale Beispiel. Es gibt 
Optimierungsstufen, bei denen der Compiler das genau so umsetzt (und 
daher "true" ermittelt), und es gibt welche, bei denen er das nicht 
umsetzt. Dann wird die Adresszuordnung dem Linker überlassen, wobei aber 
eigentlich bereits dem Compiler klar ist, dass es sich um zwei 
verschiedene Objekte im Speicher handelt, sodass er entweder selbst 
"false" einsetzen kann (optimiert) oder aber die Rechnung zur Laufzeit 
ausführen lässt (nicht optimiert).

Damit erzeugt zwar nichts davon undefined behaviour (um dessen 
potenzielle Folgen sich gerade in WG14 heiße Diskussionen ranken), aber 
es ist halt "unspecified".
#6749062
Lesenswert?

1
#include <stdio.h>
2
#include <stdlib.h>
3
#include <string.h>
4
#include <inttypes.h>
5

6
int main(int argc, char* argv[])
7
{
8
        char *p1="100";
9
        char *p2="0";
10

11
        volatile int a = p1 + 2 == p2;
12

13
        printf("p1=%p, p2=%p\r\n",p1,p2);
14

15
//      while(1);
16
}




Gerald K. schrieb:
> Werden zwei Instanzen des Programms gestartet, dann hat die Zeichenkette
> "100" zwei verschiedene Adressen.

Da muss ich mich korregieren. Ich habe ein kurzes Testpfogramm 
geschrieben um diesen Fall zu analysieren. Die Adressen sind relativ zum 
Programmcode und daher immer gleich!

Jörg W. schrieb:
> Es gibt Optimierungsstufen, bei denen der Compiler das genau so umsetzt
> (und daher "true" ermittelt)

Da wurde die Optimierung tatsächlich an die Spitze getrieben.
Angehängte Dateien:
Gast #6749139
Lesenswert?

Walter T. schrieb:
>> Meiner Meinung nach ist die Codezeile sinnloser Bullshit den
>> keine Regel von C beschreibt.

> Ich kenne keine Regel, die diese Zeile verbietet.

Dass stimmt.

Doch die C Spezifikation ist wie Datenblätter von Mikrochips. Wenn bei 
einem IC z.B. nicht festgelegt ist, wie vie mA die ESD Schutzdioden 
vertragen, dann sollte man sie gar nicht absichtlich belasten. Denn das 
kann heute 20mA sein und in der nächsten Charge nur 2mA.

Dein eigentliches Problem ist, dass es hier eine Lücke in der 
Spezifikation gibt. Du willst eine lückenlose Spezifikation. So ist C 
aber nicht und so wird es nie werden. Wenn dir das wirklich wichtig ist, 
musst du eine andere Programmiersprache wählen.

Bei Java hat man sich bewusst um eine weitgehend Lückenlose 
Spezifikation bemüht, damit Programme auf jeder Maschine gleich laufen 
(funktioniert in der Praxis leider nicht, aber zumindest hat man es 
versucht).

Bei C hat man bewusst viele Details nicht festgelegt, damit die 
Umsetzung auf allen damals relevanten Maschinen problemlos möglich ist. 
Die Konsequenz ist: Verlasse dich nie darauf, dass eine 
nicht-spezifizierte Eigenschaft woanders oder in Zukunft ebenso ist.
Gast #6749219
Lesenswert?

Jemand schrieb:
> In 6.7.9 Initialization: [..] indeterminate.

Ja, indeterminate ist klar. Du hast daraus gefolgert:

Jemand schrieb:
> dürfen also eine trap representation enthalten,

und ich frage, ob es nach 3.19.2 ff (@C11) nicht "unspecified value" 
ist.
A. S. schrieb:
> 3.19.2 indeterminate value
> either an unspecified value or a trap representation

Dann wäre es kein U.B. und das Ergebnis zwar zufällig aber ansonsten 
unkritisch.
Gast #6749230
Lesenswert?

Stefan ⛄ F. schrieb:
> Dein eigentliches Problem ist, dass es hier eine Lücke in der
> Spezifikation gibt.

Wieso Lücke? Der Original-Code ist normaler, perfekter C-Code. Dass das 
Ergebnis zufällig ist, hat nichts mit Spezifikation zu tun. Es ist 
genauso zufällig, wie die Adresse einer Funktion oder eines ints. Wenn 
ich die in ein uint8 caste und auf > 100 teste, dann kann sich das 
Ergebnis auch mit der Optimierungsstufe ändern.
Beitrag #6749237 wurde von einem Moderator gelöscht.
Beitrag #6749239 wurde von einem Moderator gelöscht.
#6749251
Lesenswert?

A. S. schrieb:
> Wieso Lücke? Der Original-Code ist normaler, perfekter C-Code.

Kommt auf deine Ansprüche bei "perfekt" an.

Schon im K&R (2. Aufl., dt, S. 99 5.4 Adreß-Arithmetik) steht:
... Wenn p und q auf Elemente im gleichen Vektor zeigen, dann 
funktionieren Vergleiche wie ==, !=, <, >= usw.
...
Der Ablauf ist jedoch undefiniert bei Arithmetik oder Vergleichen 
zwischen Zeigern, die nicht auf Elemente des gleichen Vektors verweisen. 
(Es gibt eine Ausnahme: die Adresse des ersten Elements nach dem Ende 
eines Vektors kann für Zeigerarithmetik verwendet werden.
...

Ok, auch K&R sind nicht immer perfekt. Aber als Richtschnur kann man das 
schon mal nehmen.
Gast #6749330
Lesenswert?

Klaus W. schrieb:
> Schon im K&R (2. Aufl., dt, S. 99 5.4 Adreß-Arithmetik) steht:
> ... Wenn p und q auf Elemente im gleichen Vektor zeigen, dann
> funktionieren Vergleiche wie ==, !=, <, >= usw.
> ...
> Der Ablauf ist jedoch undefiniert bei Arithmetik oder Vergleichen
> zwischen Zeigern, die nicht auf Elemente des gleichen Vektors verweisen.
> (Es gibt eine Ausnahme: die Adresse des ersten Elements nach dem Ende
> eines Vektors kann für Zeigerarithmetik verwendet werden.
> ...
>
> Ok, auch K&R sind nicht immer perfekt. Aber als Richtschnur kann man das
> schon mal nehmen.

Kann man offenbar nicht. Eine Funktion
1
int f(int* p, int* q) { return p == q; }
ist immer wohldefiniert. Wenn ein Programm mit dieser Funktion spinnt, 
liegt der Fehler nicht in f.
Beitrag #6749355 wurde von einem Moderator gelöscht.
Beitrag #6749363 wurde von einem Moderator gelöscht.
Beitrag #6749371 wurde von einem Moderator gelöscht.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren