ich habe mal eine Frage zu "Optimierungen" die ich ab und in C
Programmen sehe und wollte mal nachfragen ob das so sinnvoll ist. Falls
das Compilerspezifisch ist, bitte ich um Entschuldigung.
z.B.:
int i,test;
for (i=0;i<100000;i++)
{
test = sqrt (3) * i;
}
Das ist mal ein ganz einfaches,sinnlosen Beispiel um zu verdeutlichen
was ich meine. Ich hab schon oft gesehen, dass so etwas gemacht wurde:
#define WURZEL3 1.732050808
int i,test;
for (i=0;i<100000;i++)
{
test = WURZEL3 * i;
}
Der Autor hoffte damit wohl 100000 sqrt-Aufrufe zu ersparen. Ich hätte
wenn dann WURZEL vorher einmal mit sqrt berechnen lassen und dann
eingefügt, aber egal. Mir geht es nur darum ob das überhaupt etwas
spart. Machen evtl. sowieso alle Comiler dies so automatisch? Es wäre
doch sehr uneffektiv 100000x sqrt aufrurufen, wenn jedesmal das gleiche
raus kommt. Oder muss ich das wirklich selbst optimieren?
Falls ja, wie sieht es bei einfachen Grundrechenarten aus?
int i,test;
for (i=0;i<100000;i++)
{
test = 5 * 3 - 4 + 6;
}
Es werden doch nicht jedesmal all diese Berechnungen durchgeführt, oder?
Gruß
Andreas
Andreas Volz hat geschrieben:
> Das ist mal ein ganz einfaches,sinnlosen Beispiel um zu
> verdeutlichen was ich meine. Ich hab schon oft gesehen, dass
> so etwas gemacht wurde:
>
> #define WURZEL3 1.732050808
>
> int i,test;
>
> for (i=0;i<100000;i++)
> {
> test = WURZEL3 * i;
> }
>
> Der Autor hoffte damit wohl 100000 sqrt-Aufrufe zu ersparen.
> Ich hätte wenn dann WURZEL vorher einmal mit sqrt berechnen
> lassen und dann eingefügt, aber egal. Mir geht es nur darum
> ob das überhaupt etwas spart. Machen evtl. sowieso alle
> Comiler dies so automatisch? Es wäre doch sehr uneffektiv
Ich denke jeder vernünftige Compiler tut das automatisch,
zumindest wenn man ihm eine Optimierung einschaltet. Aber im
Extremfall passiert noch mehr, eventuell merkt der Compiler
sogar, daß das Durvchlaufen der Schleife gar nicht nötig ist,
um das Endergebnis zu erhlaten. In diesem Beispiel könnte der
Compiler also den Code einfach durch zwei Zuweisungen für i
und test ersetzen. Will man das nicht, z.B. weil man eine
Warteschleife braucht (nicht schön, aber wer weiß) muß man die
Optimierung des Compilers abschalten.
Ich weis nicht, welcher Compiler wie gut ist, aber ich denke
z.B. gcc merkt solche Stellen und optimiert solche Schleifen
weg.
CU Rollo
--
Hier entsteht in Kürze eine neue Sig-Präsenz.
Nein. Du hast ein Verständnisproblem bezüglich des Begriffes
'Algorithmus'.
> int i,test;
>
> for (i=0;i<100000;i++)
> {
> test = sqrt (3) * i;
> }
>
> Das ist mal ein ganz einfaches,sinnlosen Beispiel um zu verdeutlichen
> was ich meine. Ich hab schon oft gesehen, dass so etwas gemacht wurde:
>
> #define WURZEL3 1.732050808
>
> int i,test;
>
> for (i=0;i<100000;i++)
> {
> test = WURZEL3 * i;
> }
>
> Der Autor hoffte damit wohl 100000 sqrt-Aufrufe zu ersparen.
Irrtum. Er 'hoffte' das nicht, sondern er tat das.
> Ich hätte wenn dann WURZEL vorher einmal mit sqrt berechnen lassen
Warum willst Du einen zum Ubersetzungszeitpunkt bekannten Wert zur
Laufzeit berechnen lassen?
> und dann eingefügt, aber egal.
Nein. sqrt(x) steht für eine bestimmte Folge von
Maschinencode-Anweisungen, die ausgeführt eine angenäherte
Quadratwurzel berechnen, dh (vermutlich) sounsoviele Glieder einer
Reihe aufsummieren. Selbst wenn sich das hinter einem Maschinebefehl
versteckt, bleibt es immer noch eine aufwendige und vollkommen
überflüssige Berechnung mit a priori unbekannten Rundungsfehlern.
> Mir geht es nur darum ob das überhaupt etwas spart.
Nehmen wir mal an, wir hätten folgende Handlungsanweisung:
for (i = 0; i < 10000; ++i) {
if (sitting()) {
stand_up();
run_around_the_chair_ten_times();
}
sit_down();
grab_book();
read_a_page();
}
Warum führt die zu einer geringeren Lesegeschwindigkeit als
sit_down();
grab_book();
i = 0;
do { read_a_page(); } while (++i < 10000);
?
> Machen evtl. sowieso alle Comiler dies so automatisch? Es wäre
> doch sehr uneffektiv 100000x sqrt aufrurufen,
Exakt. Deswegen macht man es ja auch nicht.
> Oder muss ich das wirklich selbst optimieren?
Nein. Man muß es implementieren und dazu muß man den Unterschied
zwischen einer Formel und formaler Notation verstanden haben.
> Falls ja, wie sieht es bei einfachen Grundrechenarten aus?
>
> int i,test;
>
> for (i=0;i<100000;i++)
> {
> test = 5 * 3 - 4 + 6;
> }
>
> Es werden doch nicht jedesmal all diese Berechnungen durchgeführt,
> oder?
Weil der Compiler sehen kann, das der Ausdruck im Schleifenköper keine
Seiteneffekte hat, wird er ihn wahrscheinlich genau einmal berechnen
(während der Übersetzung) und evtl sogar noch die Schleife entfernen.
Was er allerdings nicht tun wird, ist folgenden Kommentar einzufügen:
/*
Please ignore the following three lines,
because they are absolutely meaningless.
I just wanted to make sure that you understand
that I am complete moron who doesn't care about
other people.
- Thanks for your attention.
*/
> Ich denke jeder vernünftige Compiler tut das automatisch,
> zumindest wenn man ihm eine Optimierung einschaltet. Aber im
> Extremfall passiert noch mehr, eventuell merkt der Compiler
> sogar, daß das Durvchlaufen der Schleife gar nicht nötig ist,
> um das Endergebnis zu erhlaten. In diesem Beispiel könnte der
> Compiler also den Code einfach durch zwei Zuweisungen für i
> und test ersetzen. Will man das nicht, z.B. weil man eine
> Warteschleife braucht (nicht schön, aber wer weiß) muß man die
> Optimierung des Compilers abschalten.
Code wie den angegebenen sollte kein Compiler optimieren können.
Beispiel:
for (int i= 0; i < 1000000; ++i)
{
x = rand(3000) * i;
}
Kann nicht optimiert werden, da das Ergebniss tatsächlich von der Zahl der
Aufrufe abhängt.
Eine Optimierung wäre nur möglich, wenn der Compiler exaktes Wissen über die
aufgerufene
Funktion hat. Das geht vielleicht bei Intrinsics, aber nicht im allgemeinen.
> Ich weis nicht, welcher Compiler wie gut ist, aber ich denke
> z.B. gcc merkt solche Stellen und optimiert solche Schleifen
> weg.
Wenn er das täte, hättest du event. ganz schnell Probleme.
Christian
> #define WURZEL3 1.732050808
> int i,test;
> for (i=0;i<100000;i++)
> {
> test = WURZEL3 * i;
> }
>
> Der Autor hoffte damit wohl 100000 sqrt-Aufrufe zu ersparen. Ich hätte
> wenn dann WURZEL vorher einmal mit sqrt berechnen lassen und dann
> eingefügt, aber egal. Mir geht es nur darum ob das überhaupt etwas
> spart. Machen evtl. sowieso alle Comiler dies so automatisch?
Da wuerde ich mich bei floating point nicht drauf verlassen, das ist
etwas haarig zu implementieren; sqrt wird von gcc etwa erst ab Version
3.4 zur Uebersetzungszeit ausgerechnet. Ausserdem koennen aufgrund von
Nichtassoziativitaet und Existenz spezieller Werte wie NaN bei
floating point viele Ausdruecke nicht optimiert werden, wie etwa x +
3.0 + 3.0. Viele Compiler bieten aber Schalter, mit denen man dies
ignorieren kann (z. B. -ffast-math bei gcc).
> Falls ja, wie sieht es bei einfachen Grundrechenarten aus?
> test = 5 * 3 - 4 + 6;
Da kann man getrost davon ausgehen, dass das jeder Compiler macht.
--
Falk
Das darf er sehr wohl. Die Namen der Standard Funktionen sind reserviert,
koennen also nicht fuer eigene Funktionen verwendet werden. Deshalb kann und
darf der Compiler wissen, wie sich sqrt() verhaelt, und er kann und darf den
Aufruf deshalb auch wegoptimieren.
Fuer den Programmierer ist nur wichtig, dass das Programm sich so verhaelt,
als ob sqrt() tatsaechlich aufgerufen worden waere. Und wenn der Compiler
direkt das Ergebnis einsetzt, dann ist genau das sichergestellt.
Gruss
Uz
--
Ullrich von Bassewitz u...@remove-to-reply.musoftware.de
1:33pm up 195 days, 20:18, 69 users, load average: 0.10, 0.12, 0.13
Um Missverständnissen vorzubeugen: sqrt() ist ein Intrinsic, daher kann der
Compiler
die erwähnte Optimierung vornehmen (das sagte ich aber auch). rand() ist
zwar eine Standard-Funktion
und wäre nach deinem Statement ebenfalls optimierbar - genau das geht aber
nicht, weil es eben _kein_
Intrinsic ist. Daher auch mein Posting: mein VP war der Meinung, das der
Compiler _solche_ Konstrukte
immer optimieren könne. Genau das stimmt aber so nicht - lies noch einmal
mein voriges Posting und
du wirst sehen, das wir eigentlich einer Meinung sind...
> Fuer den Programmierer ist nur wichtig, dass das Programm sich so
verhaelt,
> als ob sqrt() tatsaechlich aufgerufen worden waere. Und wenn der Compiler
> direkt das Ergebnis einsetzt, dann ist genau das sichergestellt.
Ack. Ist aber kein Widerspruch zu meiner Aussage.
Christian
Man kann sehr wohl.
Ansonsten könnten die Funktion selber nicht in C implementiert werden.
Oder auch andersrum: Wenn die glibc dafür ein magisches #pragma
brauchen würde, dann könnte auch jedes andere Programm dieses #pragma
verwenden.
> Deshalb kann und darf der Compiler wissen, wie sich sqrt() verhaelt,
Any feature that cannot be turned off is a bug.
> [...] Fuer den Programmierer ist nur wichtig, dass das Programm sich
> so verhaelt, als ob sqrt() tatsaechlich aufgerufen worden waere.
Und woher soll der Compiler wissen, ob der Programmierer da nicht
gerade einen Benchmark schreibt?
--
Google ist Gott. Opfere ihr deine Zeit und werde erleuchtet.
Um Mißverständnisse vorzubeugen, sollte der in C nicht existente Begriff
"Intrinsic" vermieden werden.
# zwar eine Standard-Funktion
# und wäre nach deinem Statement ebenfalls optimierbar - genau das geht aber
# nicht, weil es eben _kein_
# Intrinsic ist.
Dann solltest Du uns den Unterschied zwischen einem "Intrinsic" und
einer Standardfunktion erklären. Ein Compiler darf sehr wohl rand()
wegoptimieren, auch wenn es mehrfach aufgerufen wird. Einzig
entscheidend ist, ob ein strikt konformes Programm den Unterschied
feststellen könnte.
Regards,
Jens
--
Jens Schweikhardt http://www.schweikhardt.net/
SIGSIG -- signature too long (core dumped)
"kann" in demselben Sinne, wie man auch stehlen "kann".
# Ansonsten könnten die Funktion selber nicht in C implementiert werden.
Doch, wenn man den Unterschied zwischen Implementierer und Anwender
kennt.
# Oder auch andersrum: Wenn die glibc dafür ein magisches #pragma
# brauchen würde, dann könnte auch jedes andere Programm dieses #pragma
# verwenden.
Und das hat mit ISO C genau wieviel und was zu tun?
#> Deshalb kann und darf der Compiler wissen, wie sich sqrt() verhaelt,
#
# Any feature that cannot be turned off is a bug.
Any statement of the form "X is the one true Y" is false.
#> [...] Fuer den Programmierer ist nur wichtig, dass das Programm sich
#> so verhaelt, als ob sqrt() tatsaechlich aufgerufen worden waere.
#
# Und woher soll der Compiler wissen, ob der Programmierer da nicht
# gerade einen Benchmark schreibt?
Weil der Compiler solche Annahmen nicht zu treffen braucht. ISO C
läßt explizit alle Aussagen zu Performance offen, C99 5.1.2.3#1.
> Um Mißverständnisse vorzubeugen, sollte der in C nicht existente Begriff
> "Intrinsic" vermieden werden.
> Dann solltest Du uns den Unterschied zwischen einem "Intrinsic" und
> einer Standardfunktion erklären.
Der Begriff taucht zwar im Standard meines Wissens nicht auf, ist aber
dennoch weit verbreitet und wohl definiert.
> Ein Compiler darf sehr wohl rand()
> wegoptimieren, auch wenn es mehrfach aufgerufen wird. Einzig
> entscheidend ist, ob ein strikt konformes Programm den Unterschied
> feststellen könnte.
Da die Codesequenzen
srand(0);
for (i = 0; i < 10; ++i)
x = rand();
und
srand(0);
x = rand();
x = rand();
x = rand();
x = rand();
x = rand();
x = rand();
x = rand();
x = rand();
x = rand();
x = rand();
dann bei Optimierung der for-Schleife ein unterschiedliches Ergebniss
liefern würden, würde ein jedes Programm,
das derartigen Code enthält, den Unterschied feststellen können. Ergo läßt
sich die for-Schleife nicht optimieren.
War doch nicht schwer und hat gar nicht weh getan - oder?
Christian
Der Compiler kann, wenn er die Implementierung von rand() kennt (was nicht
unwahrscheinlich ist) im Voraus berechnen, was der zehnte Aufruf von rand()
liefert. Somit kann die Schleife und auch die Sequenz komplett wegoptimiert
werden.
Jirka
Nope: erstens müßte er dann auch die Implementierung von srand() kennen und
zweitens
müßte er sehen, welche Aufrufe von rand() welchem Aufruf von welchem srand()
folgen.
In dem von mir geposteten Code könnte er das; im allgemeinen wäre das
unmöglich, da noch weitere
Funktionsaufrufe zwischen srand() und rand() liegen könnten, die der
Compiler nicht sehen kann.
Christian
Der ISO Standard fuer die Sprache C kennt das Wort "Intrinsic" nicht. Wenn
Du's genau wissen willst: Es kommt kein einziges Mal darin vor. Aus Sicht des
Standards sind sowohl sqrt() als auch rand() Standard C Funktionen, deren
Namen reserviert sind. Wenn der Compiler weiss, wie rand() implementiert ist
(und das darf er wissen), dann kann er auch Aufrufe von rand() wegoptimieren.
Du kannst in
>> Fuer den Programmierer ist nur wichtig, dass das Programm sich so
> verhaelt,
>> als ob sqrt() tatsaechlich aufgerufen worden waere. Und wenn der Compiler
>> direkt das Ergebnis einsetzt, dann ist genau das sichergestellt.
deshalb auch sqrt() durch rand() ersetzen. Damit steht meine Aussage sehr wohl
im Widerspruch zu Deiner.
Um's nochmal deutlich zu sagen: Jeder Aufruf einer Standard C Funktion deren
Name reserviert ist (und das sind praktisch alle) darf vom Compiler
wegoptimiert werden, wenn sich das Verhalten des Programms dadurch nicht
aendert. Ob das praktikabel ist, ist eine andere Frage. sqrt() ist sicher
leichter zu optimieren als rand(). Es gibt aber keine einzige Zeile im
Standard die letzteres verbietet.
Gruss
Uz
--
Ullrich von Bassewitz u...@remove-to-reply.musoftware.de
5:12pm up 195 days, 23:57, 69 users, load average: 0.22, 0.07, 0.05
Wie oft hatten wir die Diskussion schon? Wir reden hier ueber standardkonforme
Programme, und bei denen darf man das nicht[1]. In anderen Newsgroups darfst
Du gerne auch ueber nicht standardkonforme Programme reden, bei denen das
geht. Aber nicht hier. Bitte lies Abschnitt 7.1.3 "Reserved identifiers" sowie
7.26 "Future library directions" aus "ISO/IEC 9899:1999 (E)".
> Ansonsten könnten die Funktion selber nicht in C implementiert werden.
Es ist nirgendwo im Standard festgelegt, dass die Standard Funktionen in C
implementierbar sein muessen.
>> [...] Fuer den Programmierer ist nur wichtig, dass das Programm sich
>> so verhaelt, als ob sqrt() tatsaechlich aufgerufen worden waere.
>
> Und woher soll der Compiler wissen, ob der Programmierer da nicht
> gerade einen Benchmark schreibt?
Weil im Standard das Wort "Benchmark" ueberhaupt nicht vorkommt, der Compiler
sich also darum nicht scheren muss.
[1] Es gibt eine Einschraenkung zu dem was ich gesagt habe: Die Namen der
Standard Funktionen duerfen u.a. nicht verwendet werden fuer:
- Namen mit external linkage,
- fuer Macronamen, und
- fuer Namen mit file scope visibility wenn das entsprechende Header
File eingebunden ist.
Fuer bestimmte Gruppen von Namen gibt es weitere Einschraenkungen. Alles was
mit mem... oder str... und einem weiteren Kleinbuchstaben anfaengt darf z.B.
ueberhaupt nicht verwendet werden. Was Du theoretisch tun duerftest ist, eine
Funktion sqrt() zu nennen, solange diese static ist, und math.h nicht
eingebunden wird. Ein eigenes memcpy() ist hingegen unzulaessig, egal unter
welchen Bedingungen.
Gruss
Uz
--
Ullrich von Bassewitz u...@remove-to-reply.musoftware.de
5:22pm up 196 days, 8 min, 69 users, load average: 0.00, 0.01, 0.00
> begin Ullrich von Bassewitz:
>
>> [...] Die Namen der Standard Funktionen sind reserviert,
>> koennen also nicht fuer eigene Funktionen verwendet werden.
>
> Man kann sehr wohl.
>
> Ansonsten könnten die Funktion selber nicht in C implementiert werden.
Wo fordert der Standard, dass die Standard-C-Funktionen in C
implementierbar sein müssen?
> Und woher soll der Compiler wissen, ob der Programmierer da nicht
> gerade einen Benchmark schreibt?
Das braucht der Compiler nicht zu wissen.
Gruß. Claus
Kennt er. Sieht er.
> In dem von mir geposteten Code könnte er das;
Genau. :-)
> im allgemeinen wäre das unmöglich, da noch weitere Funktionsaufrufe zwischen
> srand() und rand() liegen könnten, die der Compiler nicht sehen kann.
Das war jetzt aber nicht die Frage. Wir wollen doch mal beim Beispiel bleiben.
Jirka
Das ist schon richtig. Aber auch nur, weil die Standardbibliothek und der
Compiler meist von unterschiedlichen Herstellern stammen und für rand()
noch dazu nicht spezifiziert ist, wie es zu implementieren ist. Im Gegensatz
zu, sagen wir mal, sqrt().
Jirka
Nein. Wie bereits schon mal gepostet: ISO-C != 'world'. Es steht einer
Implementierung (oder in diesem Fall einer Familie von
Implementierungen, nämlich 'C überall außer auf embedded') vollkommen
frei, für laut ISO undefinierte Situationen ein dokumentiertes
Verhalten zu haben. Bei einem 'üblichen'
Compiler-Assembler-Linker-Arrangement sollte die Funktion aufgerufen
werden, die zuerst gefunden wird, denn man möchte ja auch
Bibliotheksfunktionen *in eigenem Code* ersetzen können.
> # Ansonsten könnten die Funktion selber nicht in C implementiert werden.
>
> Doch, wenn man den Unterschied zwischen Implementierer und Anwender
> kennt.
Der zB darin besteht, das vendor X, Y und Z dafür sorgen, daß der
Standard so aussieht, daß seine Implementierung nicht dagegen
verstößt, obwohl sie sich nicht an die Regel hält, die für 'crethi und
plethi' angeblich gelten sollen. Das funktioniert ähnlich wie xdr: Wir
nehmen das native Format unseres Systems und stellen Code, der
vorwärts und rückwärts konvertiert, kostenlos zur Verfügung, dessen
Verwendung die ganzen depperten Manager natürlich bevorzugen würden
(weniger Arbeit!!1) und lachen uns tot darüber, daß wir uns gerade
einen inhärenten Wettberwerbsvorteil 'herbeigezaubert' haben.
Falls irgendein Kommitee der Meinung ist, ich solle mich gefälligst
zugunsten von Sun, Mickeysoft, HP etc umständlicher ausdrücken, als
das sinnvoll wäre, ist das Pech für dieses Kommitee.
> #> Deshalb kann und darf der Compiler wissen, wie sich sqrt() verhaelt,
> #
> # Any feature that cannot be turned off is a bug.
>
> Any statement of the form "X is the one true Y" is false.
Falls die Aussage korret ist, 'beweist' sie, daß C für hardwarenahe
Programmierung nicht zu gebrauchen ist, denn man kann nicht warten,
weil es dem Compiler freisteht, jede Zeitverzögerung transparent zu
ignorieren. Aus naheliegenden Gründen begünstigt das Leute, die immer
noch am liebsten alles in Assembler schreiben würden und ist mir zB
vollkommen egal. Falls der Standard nicht imstande ist, ein
brauchbares Verhalten zu definieren, hat das Gremium versagt und nicht
der Mensch, der dessen Hinweise notgedrungen ignoriert.
> #> [...] Fuer den Programmierer ist nur wichtig, dass das Programm sich
> #> so verhaelt, als ob sqrt() tatsaechlich aufgerufen worden waere.
> #
> # Und woher soll der Compiler wissen, ob der Programmierer da nicht
> # gerade einen Benchmark schreibt?
>
> Weil der Compiler solche Annahmen nicht zu treffen braucht. ISO C
> läßt explizit alle Aussagen zu Performance offen, C99 5.1.2.3#1.
Er trifft aber Annahme, spezifisch die, daß ich Code schreiben wollte,
der in der kürzest möglichen Zeit abgearbeitet werden kann, und dafür
leider zu blöd war. Ich brauche aber gar kein Wekrzeug, daß mir eine
zustandsfreie und zeitlose Umgebung simuliert, weil das alles ist,
womit zurechtzukomme ich jemals gelernt habe.
Wo ist in dieser URL der Unterschied zwischen einem "Intrinsic" und
einer Standardfunktion erklärt?
# Der Begriff taucht zwar im Standard meines Wissens nicht auf, ist aber
# dennoch weit verbreitet und wohl definiert.
Dann bitte ich um die Nennung einer solchen Wohldefinition.
Im übrigen ist mir "intrinsics" nur im Zusammenhang mit X11 ein Begriff,
sonst überhaupt nicht, und da heißt es: "The Intrinsics are a
programming library tailored to the special requirements of user
interface construction within a network window system, specifically the
X Window System. The Intrinsics and a widget set make up an X Toolkit."
Das ist so X11 spezifisch, daß es mir nicht gelingen will, hier einen
allgemeinen Begriff des Programmierens zu identifizieren.
#> Ein Compiler darf sehr wohl rand()
#> wegoptimieren, auch wenn es mehrfach aufgerufen wird. Einzig
#> entscheidend ist, ob ein strikt konformes Programm den Unterschied
#> feststellen könnte.
#
# Da die Codesequenzen
#
# srand(0);
# for (i = 0; i < 10; ++i)
# x = rand();
#
# und
#
# srand(0);
# x = rand();
# x = rand();
# x = rand();
# x = rand();
# x = rand();
# x = rand();
# x = rand();
# x = rand();
# x = rand();
# x = rand();
#
# dann bei Optimierung der for-Schleife ein unterschiedliches Ergebniss
# liefern würden, würde ein jedes Programm,
# das derartigen Code enthält, den Unterschied feststellen können. Ergo läßt
# sich die for-Schleife nicht optimieren.
Doch. Z.B. könnte der Compiler den seed so wählen, daß einfach der 10.
Wert für rand() als nächstes erscheint. Darüberhinaus hat dein
Codeschnipsel *überhauptkeinen* Effekt und könnte vollständig entfernt
werden. Also ist es besser, wenn wir uns in dieser Diskussion auf
vollständige Programme inklusive Seiteneffekten wie Ausgabe
konzentrieren.
# War doch nicht schwer und hat gar nicht weh getan - oder?
Ist schwerer als Du denkst! Also
#include <stdio.h>
#include <stdlib.h>
int main (void)
{
int x;
srand (0);
for (i = 0; i < 10; ++i)
x = rand ();
printf ("%d\n", x);
return 0;
}
kann sehr wohl zu jedem Programm optimiert werden, das äquivalent zu
puts ("42"); ist, wenn der 10. rand() 42 liefert.
Nein: da rand() Seiteneffekte hat (ändern der Seed) und die Seed beim ersten
(ggf. wegzuoptimierenden) Aufruf
dem Compiler im allgemeinen nicht bekannt sein kann; gibt es für ihn keine
Möglichkeit; die Aufrufe wegzuoptimieren.
Das wäre nur in einer Ausnahme möglich (ich erwähnte es bereits): wenn dem
Compiler a) die zur Laufzeit vorliegende
seed und b.) das exakte Verhalten von rand() kennen würde. In der Realität
kommt das nicht vor.
> deshalb auch sqrt() durch rand() ersetzen. Damit steht meine Aussage sehr
wohl
> im Widerspruch zu Deiner.
Es gibt einen Unterschied: sqrt() ist 1.) seiteneffektfrei und 2.) ist das
Verhalten von sqrt() wohldefiniert.
Daher hätte ein Compiler bei sqrt() eine Chance zu optimieren, bei rand()
nicht.
> Um's nochmal deutlich zu sagen: Jeder Aufruf einer Standard C Funktion
deren
> Name reserviert ist (und das sind praktisch alle) darf vom Compiler
> wegoptimiert werden, wenn sich das Verhalten des Programms dadurch nicht
> aendert.
Noch nicht mal so eng: genaugenommen darf der Compiler alles mögliche
optimieren (ob bekannte oder
unbekannte Funktion), solange sich die Funktionsweise des Programmes nicht
ändert. Die Frage des OP
war aber, in welchen Fällen ein Compiler das könnte.
> Ob das praktikabel ist, ist eine andere Frage. sqrt() ist sicher
> leichter zu optimieren als rand(). Es gibt aber keine einzige Zeile im
> Standard die letzteres verbietet.
Das habe ich auch nie behauptet. Ich sagte, das es Fälle gibt, in denen der
Compiler selbst bei Standard-C-Funktionen
Aufrufe nicht optimieren kann - weil es schlichtweg technisch mangels
vollständiger Informationen bnicht gehen kann!
Christian
In der URL? Gar nicht. Aber solltest du jemals auf die geniale Idee kommen,
diese URL einem fähigen Browser zwecks
Öffnens der Seite zu überantworten, so könntest du eine Begriffsdefinition
erhalten. Ach ja: lesen müßtest du die Seite in
dem Fall allerdings auch.
> Dann bitte ich um die Nennung einer solchen Wohldefinition.
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vclang/html
/vcrefmmxtechnologyintrinsicgroups.asp
http://www.tacc.utexas.edu/resources/user_guides/intel/c_ug/linux112.htm
> Im übrigen ist mir "intrinsics" nur im Zusammenhang mit X11 ein Begriff,
> sonst überhaupt nicht, und da heißt es: "The Intrinsics are a
> programming library tailored to the special requirements of user
> interface construction within a network window system, specifically the
> X Window System. The Intrinsics and a widget set make up an X Toolkit."
Mit veralteten Betriebsystemen muß ich mich dankenswerterweise nicht mehr
befassen.
> Doch. Z.B. könnte der Compiler den seed so wählen, daß einfach der 10.
> Wert für rand() als nächstes erscheint.
Sicher, wenn er denn wüßte, was der 10. Wert für rand() ist. Und dazu müßte
er den seed,
der beim ersten Aufruf gerade vorliegt, kennen...
> Darüberhinaus hat dein Codeschnipsel *überhauptkeinen* Effekt und könnte
vollständig entfernt
> werden. Also ist es besser, wenn wir uns in dieser Diskussion auf
> vollständige Programme inklusive Seiteneffekten wie Ausgabe
> konzentrieren.
Das ist ja nun wirklich Unfug: jedes Codefragment, das man zu dieser
Diskussion hier posten würde,
hätte für sich alleine keinen Nutzeffekt und könnte vollständig eleminiert
werden. Sich auf "vollständige Programme"
zu konzentrieren ist erst Recht Quatsch: Es soll ja Leute geben, die Libs
basteln; die haben überhaupt keine
vollständigen Programme, an denen sie untersuchen könnten!
> #include <stdio.h>
> #include <stdlib.h>
>
> int main (void)
> {
> int x;
>
> srand (0);
> for (i = 0; i < 10; ++i)
> x = rand ();
> printf ("%d\n", x);
> return 0;
> }
>
> kann sehr wohl zu jedem Programm optimiert werden, das äquivalent zu
> puts ("42"); ist, wenn der 10. rand() 42 liefert.
Ich habe nie etwas anderes behauptet!
Aber:
#include <stdio.h>
#include <stdlib.h>
#include "someUnknownFunc.h"
void setSeed(int s)
{
seed(s * rand());
}
int test10()
{
int x;
for (i = 0; i < 10; ++i)
x = rand ();
return x;
}
int main (void)
{
someUnknownFunc(); // Diese Funktion möge in irgendeiner Lib liegen
und irgendetwas machen
// wie z.B. gar nichts; seed()
aufrufen, rand() aufrufern oder sonst etwas.
setSeed(test10());
setSeed(test10());
printf ("%d\n", x);
return 0;
}
kann nicht optimiert werden! Dem Compiler würden für jedwede Optimierung
bzgl. der Funktion test10() Informationen fehlen.
Darum ging es beim OP: wann kann ein Compiler optimieren und wann wird er es
tun? Den zweiten Teil der Frage kann man
sowieso nicht allgemeingültig beantworten (da Compilerabhängig), und beim
ersten Teil ist es auch interessant zu wissen,
wann nicht optimiert werden kann. Und das Beispiel zeigt, das es selbst bei
Standard-C-Funktionen möglich ist, das der Compiler
keine Optimierung ausführen kann. Das aber hast du behauptet. Richtig ist:
nur bei Standard-C-Funktionen _kann_ der Compiler
die Informationen haben, die er für eine Optimierung bräuchte; aber im
Allgemeinen _hat_ er sie einfach nicht.
Christian
> Es gibt einen Unterschied: sqrt() ist 1.) seiteneffektfrei und 2.) ist das
> Verhalten von sqrt() wohldefiniert.
> Daher hätte ein Compiler bei sqrt() eine Chance zu optimieren, bei rand()
> nicht.
sqrt hat auch Seiteneffekte; es setzt ERRNO. Irgendwie sehe ich den
prinzipiellen Unterschied nicht. (Den praktischen durchaus, es wird
kaum ein Compiler versuchen, rand() zu optimieren, einfach weil sich
das nicht loht.)
--
Falk
Beim Start des Programms verhaelt sich rand() so, als ob vorher srand() mit
dem Wert 1 aufgerufen worden waere. Das definiert der Standard. Deshalb gibt
es Programme, bei denen der Compiler sehr wohl wissen kann, was ein bestimmter
Aufruf von rand() zurueckgibt, und in diesen Faellen ist es dem Compiler
erlaubt, den Aufruf von rand() wegzuoptimieren.
Zugegeben: Das sind einige "wenn"s. Den "wenn" Fall gibt's fuer sqrt aber
auch:
double x = 3.0;
...
double y = sqrt (x);
Wenn der Compiler feststellen kann, dass beim Aufruf von sqrt immer nur 3.0
uebergeben wird, dann kann er den Aufruf wegoptimieren. Auch hier gilt das
"wenn".
Das einzige wo Du eventuell recht hast ist, dass es wohl keinen Compilerbauer
geben wird, der tatsaechlich Arbeit in die Optimierung von rand() steckt. Das
ist aber ein anderes Problem. Der Standard erlaubt die Optimierung sehr wohl,
und es gibt genug Funktionen wo es weniger eindeutig ist, und wo manche
Compiler optimieren und andere nicht (sqrt() werden wohl die meisten
optimieren, weil es nicht sehr schwierig zu implementieren ist).
> Richtig ist:
> nur bei Standard-C-Funktionen _kann_ der Compiler
> die Informationen haben, die er für eine Optimierung bräuchte; aber im
> Allgemeinen _hat_ er sie einfach nicht.
Nichts anderes habe ich behauptet. Es gab aber sowohl jemanden, der die
Wegoptimierung des Funktionsaufrufs generell verbieten wollte ("wer weiss ob
da ein Benchmark drin steckt") und einen anderen, der zwischen "Intrinsics"
und normalen Funktionen unterscheiden wollte. Beides ist schlicht falsch und
wird vom Standard nicht gedeckt.
Gruss
Uz
--
Ullrich von Bassewitz u...@remove-to-reply.musoftware.de
12:03am up 196 days, 6:48, 69 users, load average: 0.13, 0.15, 0.13
Das korrekte Verb wäre 'zu ignorieren'.
> Das einzige wo Du eventuell recht hast ist, dass es wohl keinen
> Compilerbauer geben wird, der tatsaechlich Arbeit in die Optimierung
> von rand() steckt.
gcc wird das irgendwann tun, nur keine Panik. Ansonsten stellt sich
die Frage, woher der Compiler weiß, was das Programm tun sollte,
inwiefern also ein anderes Programm diese Aufgabe besser erledigen
könnte. Falls ich
a = rand();
schreibe und ein Compiler übersetzt das zu
a = 0;
ist das zunächst mal bloß anders.
> Das ist aber ein anderes Problem. Der Standard erlaubt die
> Optimierung sehr wohl,
Was verbessert sie denn im allgemeinen Fall?
a = time();
b = rand();
printf("%d\n", time() - a);
>> Richtig ist: nur bei Standard-C-Funktionen _kann_ der Compiler
>> die Informationen haben, die er für eine Optimierung bräuchte; aber im
>> Allgemeinen _hat_ er sie einfach nicht.
>
> Nichts anderes habe ich behauptet. Es gab aber sowohl jemanden, der die
> Wegoptimierung des Funktionsaufrufs generell verbieten wollte ("wer weiss ob
> da ein Benchmark drin steckt")
... oder eine Verzögerungsschleife. Jedenfalls kann ein 'conforming
program' einen Unterschied feststellen (siehe oben), ergo wäre das
Entfernen das Funtionsaufrufes verboten. Ich habe bewußt 'wäre'
geschrieben, weil ein 'Compilerbauer' das auch nicht zwangsläufig
verstehen muß, und, wie zB die 'Optimierung' von printf("string\n") zu
puts("string") durch gcc zeigt, auch wahrscheinlich nicht tut.
Das hast Du gerade frei erfunden.
If the program declares or defines an identifier in a context
in which it is reserved (other than as allowed by 7.1.4), or
defines a reserved identifier as a macro name, the behavior is
undefined.
Falls man Deiner Aussage Glauben schenkt, sind bspw valgrind oder
libefence 'verbotene Programme' (netter Einfall,
wirklich). Tatsächlich sind beide aber sogar 'conforming', bloß nicht
'strictly conforming'.
Ach ja, Du möchtest meinen Namen von dieser Seite löschen:
<URL:http://www.von-bassewitz.de/uz/killfile.php>
denn ich habe Dir keinerlei Erlaubnis erteilt, ihn in dieser Form zu
veröffentlichen.
I started thinking about a kill file some time in 2001, when I
noticed that just asking a simple question in
de.comp.os.linux.misc, would result in tons of flames, and
that most of these flames came from just a few people. I
ignored these people whenever I visited the group, but it was
hard work sometimes.
Die Behauptung ist bezogen auf mich nachweislich falsch und somit in
Deutschland illegal.
> "Christian Janßen" <c...@christian-janszen.de> writes:
>
>> Es gibt einen Unterschied: sqrt() ist 1.) seiteneffektfrei [...]
>
> sqrt hat auch Seiteneffekte; es setzt ERRNO.
Nur bei Auftreten eines bestimmten, wohl definierten Fehlers, der im
Ursprungsposting nicht existiert. Ist dem Compiler dieser Umstand
bekannt, kann er sehr wohl optimieren. Und selbst wenn dieser Fehler
existieren würde, könnte er optimiern.
Außerdem verlangt der Standard IMHO nirgends, dass die
Standardfunktionen auch wirklich als echte Funktionen implementiert sein
müssen.
Im Übrigen heißt die Variable errno, nicht ERRNO ;-)
Gruß. Claus
Rainer Weikusat <weik...@students.uni-mainz.de> wrote:
> u...@remove-to-reply.musoftware.de (Ullrich von Bassewitz) writes:
>> Das einzige wo Du eventuell recht hast ist, dass es wohl keinen
>> Compilerbauer geben wird, der tatsaechlich Arbeit in die Optimierung
>> von rand() steckt.
> gcc wird das irgendwann tun, nur keine Panik. Ansonsten stellt sich
> die Frage, woher der Compiler weiß, was das Programm tun sollte,
> inwiefern also ein anderes Programm diese Aufgabe besser erledigen
> könnte. Falls ich
> a = rand();
> schreibe und ein Compiler übersetzt das zu
> a = 0;
> ist das zunächst mal bloß anders.
Das ist auch keine korrekte "Optimierung" von rand().
Wenn 'rand' definiert ist als
int seed;
int srand(int n) { seed = n; }
int rand() { return (seed = 12345 * seed + 23) & 0x7fff; }
wäre eine korrekte Optimierung
srand(0);
a = rand();
->
a = 23;
srand(23);
>> Das ist aber ein anderes Problem. Der Standard erlaubt die
>> Optimierung sehr wohl,
> Was verbessert sie denn im allgemeinen Fall?
Es sind immerhin Verbesserungen möglich, wenn ein Programm
mehrere Zufallszahlen nacheinander abruft. Da gibt's im Knuth
ein paar schicke Formeln für ('wie bekomme ich die Zufallszahl,
die mir eine lineare Kongruenz nach 1000 Schritten liefern
würde?').
Allerdings dürfte sich das meiste davon auch durch agressives
Inlining erledigen lassen.
> a = time();
> b = rand();
> printf("%d\n", time() - a);
Und? Egal was der Compiler für 'rand()' einsetzt. Wenn ich den
Rechner zwischendurch in den suspend-to-RAM-Modus schicke,
stellt das alles mögliche fest, nur keine Eigenschaft von
'rand()'. Oder wenn ich mit dem Debugger durchgehe. Oder wenn
der Scheduler dazwischen haut. Oder time_t wrappt.
Abgesehen davon, daß das Programm bei 16-bit ints nicht tut.
>>> Richtig ist: nur bei Standard-C-Funktionen _kann_ der Compiler
>>> die Informationen haben, die er für eine Optimierung bräuchte; aber im
>>> Allgemeinen _hat_ er sie einfach nicht.
>>
>> Nichts anderes habe ich behauptet. Es gab aber sowohl jemanden, der die
>> Wegoptimierung des Funktionsaufrufs generell verbieten wollte ("wer weiss ob
>> da ein Benchmark drin steckt")
> ... oder eine Verzögerungsschleife. Jedenfalls kann ein 'conforming
> program' einen Unterschied feststellen (siehe oben),
Ein 'conforming program' kann auch gleich
#pragma do_not_optimize_rand
sagen, da es ja nur von mindestens einer Implementation
akzeptiert werden muß.
Ein 'strictly conforming' Programm kann keinen Unterschied
feststellen, da es keinen Weg gibt, an Vergleichswerte zu
gelangen. Wenn obiges Programm immer 0 ausgibt, was hast du dann
davon? Wenn du es mit anderen Compiler-Optionen neu übersetzt
und eins erhältst, das immer 1 ausgibt, ist das ein neues
Programm, da es mit einer anderen Implementierung übersetzt
wurde. Auch wenn die Compiler.exe jedes Mal dieselbe ist, sobald
du an der Optimierung (oder an '-ffreestanding', oder
'-funsigned-char') drehst, ist es für ISO C eine neue
Implementierung.
> ergo wäre das Entfernen das Funtionsaufrufes verboten. Ich
> habe bewußt 'wäre' geschrieben, weil ein 'Compilerbauer' das
> auch nicht zwangsläufig verstehen muß, und, wie zB die
> 'Optimierung' von printf("string\n") zu puts("string") durch
> gcc zeigt, auch wahrscheinlich nicht tut.
printf->puts ist für eine Hosted-Umgebung eine zulässige
Optimierung, auch wenn du tausendmal das Gegenteil behauptest.
Bitte Kapitel und Vers zitieren. Ich
Ich warte ja noch auf deine Implementierung von ISO C, die all
die ständig angemeckerten "Probleme" nicht hat.
Stefan
--
Welcher Idiot hat eigentlich verbrochen, daß mit 'gcc -ansi',
libc5 und Linux-2.4 keinerlei nichttriviales Programm mehr
übersetzbar ist?
Findest Du es hilfreich, auf konkrete Fragen irgendwelche "Antworten"
zu geben, die mit der Frage nur marginal zu tun haben?
# Aber solltest du jemals auf die geniale Idee kommen,
# diese URL einem fähigen Browser zwecks
# Öffnens der Seite zu überantworten, so könntest du eine Begriffsdefinition
# erhalten. Ach ja: lesen müßtest du die Seite in
# dem Fall allerdings auch.
Habe ich gemacht. Warum verwechselst Du ein Deutsch-Englisch Wörterbuch
mit einer Begriffserklärung?
#> Dann bitte ich um die Nennung einer solchen Wohldefinition.
#
# http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vclang/html
# /vcrefmmxtechnologyintrinsicgroups.asp
Eine Intrinsic ist also ein Satz von i386 MMX Zugriffsfunktionen in C++?
Kennst Du eigentlich den Unterschied zwischen einer Definition und
einem Beispiel?
#> Im übrigen ist mir "intrinsics" nur im Zusammenhang mit X11 ein Begriff,
#> sonst überhaupt nicht, und da heißt es: "The Intrinsics are a
#> programming library tailored to the special requirements of user
#> interface construction within a network window system, specifically the
#> X Window System. The Intrinsics and a widget set make up an X Toolkit."
#
# Mit veralteten Betriebsystemen muß ich mich dankenswerterweise nicht mehr
# befassen.
Schön, daß Du DOS geknickt hast. X11 hast Du offensichtlich nie benutzt,
denn es ist kein Betriebsystem, das nur am Rande. Gerade habe ich google
nach intrinsic in de.comp.lang.c gefragt, seit Anbeginn der Zeitrechnung
kam es außerhalb dieses Threads viermal vor. Ich halte den Begriff
deshalb nicht für einen in dieser Gruppe und in C allgemein nützlichen,
geschweige denn anerkannten Begriff.
#> Doch. Z.B. könnte der Compiler den seed so wählen, daß einfach der 10.
#> Wert für rand() als nächstes erscheint.
#
# Sicher, wenn er denn wüßte, was der 10. Wert für rand() ist. Und dazu müßte
# er den seed,
# der beim ersten Aufruf gerade vorliegt, kennen...
Überraschung! Genau das weiß er: ISO C99 7.20.2.2 "If rand is called
before any calls to srand have been made, the same sequence shall be
generated as when srand is first called with a seed value of 1."
Vielleicht solltest Du Deine Annahmen prüfen, bevor Du so leicht
angreifbare Aussagen machst.
#> Darüberhinaus hat dein Codeschnipsel *überhauptkeinen* Effekt und könnte
# vollständig entfernt
#> werden. Also ist es besser, wenn wir uns in dieser Diskussion auf
#> vollständige Programme inklusive Seiteneffekten wie Ausgabe
#> konzentrieren.
#
# Das ist ja nun wirklich Unfug: jedes Codefragment, das man zu dieser
# Diskussion hier posten würde,
# hätte für sich alleine keinen Nutzeffekt und könnte vollständig eleminiert
# werden.
Unfug. Jedes Schnipsel mit Ein/Ausgabe hat solche Seiteneffekte.
#> #include <stdio.h>
#> #include <stdlib.h>
#>
#> int main (void)
#> {
#> int x;
#>
#> srand (0);
#> for (i = 0; i < 10; ++i)
#> x = rand ();
#> printf ("%d\n", x);
#> return 0;
#> }
#>
#> kann sehr wohl zu jedem Programm optimiert werden, das äquivalent zu
#> puts ("42"); ist, wenn der 10. rand() 42 liefert.
#
# Ich habe nie etwas anderes behauptet!
Dann muß ich Deinem Gedächtnis auf die Sprünge helfen. Du schriebst:
Code wie den angegebenen sollte kein Compiler optimieren können.
Beispiel:
for (int i= 0; i < 1000000; ++i)
{
x = rand(3000) * i;
}
Kann nicht optimiert werden, da das Ergebniss tatsächlich von der Zahl
der Aufrufe abhängt. Eine Optimierung wäre nur möglich, wenn der
Compiler exaktes Wissen über die aufgerufene Funktion hat. Das geht
vielleicht bei Intrinsics, aber nicht im allgemeinen.
Nur um Deine Fantasie mal ein wenig anzukurbeln: Das obige ist trivial
optimierbar: Der Compiler generiert kurz den Code, führt ihn aus und
schaut nach dem Ergebnis in x, erzeugt dann tatsächlich nur eine
Instruktion x = Ergebnis. Voilà! Ist eine Form von
Laufzeit-Invariantenoptimierung.
...[code mit Aufruf zu unbekannter Funktion]...
# kann nicht optimiert werden!
Stelle ich nicht in Abrede.
# Dem Compiler würden für jedwede Optimierung
# bzgl. der Funktion test10() Informationen fehlen.
Korrekt.
# Darum ging es beim OP: wann kann ein Compiler optimieren und wann wird er es
# tun?
Genau.
# Den zweiten Teil der Frage kann man
# sowieso nicht allgemeingültig beantworten (da Compilerabhängig), und beim
# ersten Teil ist es auch interessant zu wissen,
# wann nicht optimiert werden kann. Und das Beispiel zeigt, das es selbst bei
# Standard-C-Funktionen möglich ist, das der Compiler
# keine Optimierung ausführen kann.
# Das aber hast du behauptet.
Nein. Ich habe Deine Behauptung widerlegt, rand() Sequenzen seien
nicht wegoptimierbar. Wie Du das so verallgemeinerst ist mir rätselhaft.
# Richtig ist:
# nur bei Standard-C-Funktionen _kann_ der Compiler
# die Informationen haben, die er für eine Optimierung bräuchte;
Auch bei allen anderen Funktionen, die er in der gleichen Translation
Unit übersetzt.
# aber im Allgemeinen _hat_ er sie einfach nicht.
Welcher Compiler wann wieviel Intelligenz für Optimierungen aufwendet
ist ein weites Feld, das sich täglich ändert. Daher sind alle Aussagen
diesbezüglich prinzipiell vage. Ich spreche daher von den theoretisch
möglichen Optimierungen, und anders als Du kenne ich den Standard, weiß
welche Aussagen er zur abstrakten Maschine und zur Programmausführung
macht und argumentiere entsprechend.
In der Tat. Es ist ein Austauschen von Programmteilen nach Maßgabe
einer undokumentierten Richtlinie auf der Basis von ein paar Annahmen,
was ich 'eigentlich hätte schreiben wollen', die sich auf nichts
gründen.
>>> Das ist aber ein anderes Problem. Der Standard erlaubt die
>>> Optimierung sehr wohl,
>
>> Was verbessert sie denn im allgemeinen Fall?
>
> Es sind immerhin Verbesserungen möglich, wenn ein Programm
> mehrere Zufallszahlen nacheinander abruft.
Du hast die Frage nicht beantwortet. Woher weiß der Compiler, welcher
Algorithmus zur Lösung eines im unbekannten Problems 'optimal' ist und
wie ist 'optimal' in diesem Zusammenhang definiert? Hier geht es
immerhin nicht darum, Maschinenbefehle umzuordnen, sondern
Programmsemantik 'silently' zu ändern. Der einzige Effekt, der mir bis
jetzt praktisch aufgefallen ist, ist der, daß mit irgendwelchen wirren
und unportablen Tricks dafür sorgt, daß der Optimizer den Code in Ruhe
läßt, weil er seine primitiven Analysemöglichkeiten übersteigt.
>> a = time();
>> b = rand();
>> printf("%d\n", time() - a);
>
> Und? Egal was der Compiler für 'rand()' einsetzt. Wenn ich den
> Rechner zwischendurch in den suspend-to-RAM-Modus schicke,
Gibt es in C nicht.
> stellt das alles mögliche fest, nur keine Eigenschaft von
> 'rand()'. Oder wenn ich mit dem Debugger durchgehe.
Gibt es in C nicht.
> Oder wenn der Scheduler dazwischen haut.
Gibt es in C nicht.
> Oder time_t wrappt.
Kann es nicht. Es ist signed, das Überlaufverhalten also
undefiniert.
> Abgesehen davon, daß das Programm bei 16-bit ints nicht tut.
'implicit int' gibt es nicht mehr.
>>> Nichts anderes habe ich behauptet. Es gab aber sowohl jemanden, der die
>>> Wegoptimierung des Funktionsaufrufs generell verbieten wollte ("wer weiss ob
>>> da ein Benchmark drin steckt")
>
>> ... oder eine Verzögerungsschleife. Jedenfalls kann ein 'conforming
>> program' einen Unterschied feststellen (siehe oben),
>
> Ein 'conforming program' kann auch gleich
> #pragma do_not_optimize_rand
> sagen, da es ja nur von mindestens einer Implementation
> akzeptiert werden muß.
Siehe oben.
>> ergo wäre das Entfernen das Funtionsaufrufes verboten. Ich
>> habe bewußt 'wäre' geschrieben, weil ein 'Compilerbauer' das
>> auch nicht zwangsläufig verstehen muß, und, wie zB die
>> 'Optimierung' von printf("string\n") zu puts("string") durch
>> gcc zeigt, auch wahrscheinlich nicht tut.
>
> printf->puts ist für eine Hosted-Umgebung eine zulässige
> Optimierung, auch wenn du tausendmal das Gegenteil behauptest.
> Bitte Kapitel und Vers zitieren. Ich
Das hatte ich bereits getan. Das hier ist strictly conforming:
#include <stdio.h>
#include <time.h>
#include <stdlib.h>
int main(void)
{
clock_t t0;
t0 = clock();
sqrt(4);
sqrt(4);
sqrt(4);
sqrt(4);
sqrt(4);
sqrt(4);
sqrt(4);
sqrt(4);
sqrt(4);
sqrt(4);
sqrt(4);
sqrt(4);
sqrt(4);
t0 = clock() - t0;
return t0;
}
Den 'Unterschied' kann ich nur dann nicht festellen, falls clock() bei
einer konkreten Implementierung immer -1 liefert. Dann dürfte man
sowas 'optimieren'. Du darfst mich widerlegen. Und vielleicht die
Frage beantworten, was hier eigentlich nach Maßgabe von wessen besser
oder schlechter ist.
Sind wir wieder am staenkern, ja? Netter Trick, eine ungueltige From Adresse
zu verwenden, um aus meinem Killfile rauszukommen.
Was ich geschrieben habe steht genau so in den genannten Abschnitten des
Standards. Ich akzeptiere auch, wenn Du nicht meiner Meinung bist, aber wenn
Du willst, dass ich Dir auch glaube, dann musst Du schon ein bischen mehr
Substanz rueberbringen. Aber es gab wohl einen Grund, dass Du bei mir im
Killfile stehst ...
> If the program declares or defines an identifier in a context
> in which it is reserved (other than as allowed by 7.1.4), or
> defines a reserved identifier as a macro name, the behavior is
> undefined.
Lies nochmal den kompletten Abschnitt 7.1.3, wenn es Dir tatsaechlich darum
geht, zu verstehen, worauf ich mich bezogen habe. Wenn es nur um's staenkern
ging brauchst Du das natuerlich nicht.
> Falls man Deiner Aussage Glauben schenkt, sind bspw valgrind oder
> libefence 'verbotene Programme' (netter Einfall,
> wirklich). Tatsächlich sind beide aber sogar 'conforming', bloß nicht
> 'strictly conforming'.
Es geht in dieser Gruppe aussschliesslich um "strictly conforming" Programme,
und ja, sowohl valgrind und efence sind das nicht. "strictly conforming"
Programme sind solche, die nur Features verwenden, die im Standard definiert
sind. Programme die bloss "conforming" sind koennen alles moegliche verwenden,
was ein C Compiler so anbietet. Das Programm
10 FOR I = 1 TO 10
20 PRINT I
30 NEXT I
kann "conforming" sein, ist aber nie "strictly conforming".
> Ach ja, Du möchtest meinen Namen von dieser Seite löschen:
>
> <URL:http://www.von-bassewitz.de/uz/killfile.php>
>
> denn ich habe Dir keinerlei Erlaubnis erteilt, ihn in dieser Form zu
> veröffentlichen.
Ich sehe dort nirgendwo "Rainer Weikusat" stehen, bin aber gerne bereit, Deine
Mailadresse zu verfremden.
> I started thinking about a kill file some time in 2001, when I
> noticed that just asking a simple question in
> de.comp.os.linux.misc, would result in tons of flames, and
> that most of these flames came from just a few people. I
> ignored these people whenever I visited the group, but it was
> hard work sometimes.
>
> Die Behauptung ist bezogen auf mich nachweislich falsch und somit in
> Deutschland illegal.
Lies den gesamten(!) Text auf der Seite nochmal. Es gibt keinen Bezug zwischen
Dir und obigem Abschnitt. Der Abschnitt erlaeutert, warum ich begonnen habe,
ein Killfile zu fuehren. Er gibt nicht die Begruendung dafuer, warum einzelne
Leute bei mir im Killfile stehen. Das ist voellig offensichtlich, wenn man den
Text auf der Seite liest (ich bin aber gerne bereit, dass noch deutlicher zu
formulieren).
Rainer, Du hast Dich in den letzten Jahren wirklich veraendert. Vor vier
Jahren habe ich gerne gelesen, was Du geschrieben hast, und wenn ich damals
schon ein Killfile gehabt haette, dann haettest Du eher einen positiven Score
bekommen als einen negativen. Ich weiss nicht was mit Dir passiert ist, aber
Du bist immer muffeliger, unfreundlicher und staenkeriger geworden. Daraufhin
bist Du mehrfach fuer kurze Zeit bei mir im Killfile gelandet und jetzt
dauerhaft. Schade drum.
Gruss
Uz
P.S.: Ich habe .invalid jetzt auch im Killfile. Entweder Du laesst Dir nochmal
was neues einfallen, oder Du verwendest in Zukunft Mail fuer solche Sachen,
wie es eigentlich am sinnvollsten waere.
--
Ullrich von Bassewitz u...@remove-to-reply.musoftware.de
11:59am up 196 days, 18:45, 69 users, load average: 0.07, 0.05, 0.09
> Findest Du es hilfreich, auf konkrete Fragen irgendwelche "Antworten"
> zu geben, die mit der Frage nur marginal zu tun haben?
Findest du es sinnvoll, danach zu fragen, wo in einer URL eine
Begriffsdefinition stehen könnte?
> Eine Intrinsic ist also ein Satz von i386 MMX Zugriffsfunktionen in C++?
> Kennst Du eigentlich den Unterschied zwischen einer Definition und
> einem Beispiel?
War nur ein Beispiel. Wenn dir das nicht reicht, tust du mir leid.
> Schön, daß Du DOS geknickt hast. X11 hast Du offensichtlich nie benutzt,
> denn es ist kein Betriebsystem, das nur am Rande.
Weiss ich - X wird aber nur auf veralteten Betriebssystemen eingesetzt. Gut,
es gibt
ein paar Verrückte, die meinen, das auch unter Windows haben zu müssen...
> Überraschung! Genau das weiß er: ISO C99 7.20.2.2 "If rand is called
> before any calls to srand have been made, the same sequence shall be
> generated as when srand is first called with a seed value of 1."
> Vielleicht solltest Du Deine Annahmen prüfen, bevor Du so leicht
> angreifbare Aussagen machst.
Wobei du allerdings davon ausgehst, das der Compiler weiß, welcher Aufruf
von rand()
chronologisch der erste ist.
> Unfug. Jedes Schnipsel mit Ein/Ausgabe hat solche Seiteneffekte.
Ich habe kein Codefragment mit Ein-/Ausgabe gepostet...
> Code wie den angegebenen sollte kein Compiler optimieren können.
> Beispiel:
>
> for (int i= 0; i < 1000000; ++i)
> {
> x = rand(3000) * i;
> }
>
> Kann nicht optimiert werden, da das Ergebniss tatsächlich von der Zahl
> der Aufrufe abhängt. Eine Optimierung wäre nur möglich, wenn der
> Compiler exaktes Wissen über die aufgerufene Funktion hat. Das geht
> vielleicht bei Intrinsics, aber nicht im allgemeinen.
>
> Nur um Deine Fantasie mal ein wenig anzukurbeln: Das obige ist trivial
> optimierbar: Der Compiler generiert kurz den Code, führt ihn aus und
> schaut nach dem Ergebnis in x, erzeugt dann tatsächlich nur eine
> Instruktion x = Ergebnis. Voilà! Ist eine Form von
> Laufzeit-Invariantenoptimierung.
Die aber nur funktioniert, wenn der Compiler den gesamten chronologisch vor
dem zu optimierenden Code
auszuführenden Code ebenfalls "mal schnell ausführt" - was in der weitaus
größeren Zahl aller Fälle
undenkbar ist (insbesondere, wenn noch Benutzereingaben den Ablauf steuern).
> # Den zweiten Teil der Frage kann man
> # sowieso nicht allgemeingültig beantworten (da Compilerabhängig), und
beim
> # ersten Teil ist es auch interessant zu wissen,
> # wann nicht optimiert werden kann. Und das Beispiel zeigt, das es selbst
bei
> # Standard-C-Funktionen möglich ist, das der Compiler
> # keine Optimierung ausführen kann.
>
> # Das aber hast du behauptet.
>
> Nein. Ich habe Deine Behauptung widerlegt, rand() Sequenzen seien
> nicht wegoptimierbar. Wie Du das so verallgemeinerst ist mir rätselhaft.
Ich habe nicht behauptet, das rand()-Sequenzen _nie_ optimierbar wären: das
sie in trivialen Fällen
optimierbar sind, will ich ja noch glauben - aber im Allgemeinen geht das
nicht!
> Auch bei allen anderen Funktionen, die er in der gleichen Translation
> Unit übersetzt.
Ack.
> Welcher Compiler wann wieviel Intelligenz für Optimierungen aufwendet
> ist ein weites Feld, das sich täglich ändert. Daher sind alle Aussagen
> diesbezüglich prinzipiell vage. Ich spreche daher von den theoretisch
> möglichen Optimierungen,
Da sind wir ja tatsächlich mal einer Meinung...
> und anders als Du kenne ich den Standard, weiß
> welche Aussagen er zur abstrakten Maschine und zur Programmausführung
> macht und argumentiere entsprechend.
Woher willst du wissen, was ich weiß?
Christian
Ulrich, das ist mein bitterer Ernst: Ich habe Aussicht auf eine Art
regulären Job und Du *wirst* Post von einem Anwalt bekommen, falls Du
nicht aufhörst, mich ohne Grund öffentlich zu beleidigen. Nimm das als
offiziellen Androhung einer Handlung im Wiederholungsfall. Falls Du es
nicht liest - Pech. Mir langts jedenfalls. Dito für Herrn Reibenstein.
>> If the program declares or defines an identifier in a context
>> in which it is reserved (other than as allowed by 7.1.4), or
>> defines a reserved identifier as a macro name, the behavior is
>> undefined.
>
> Lies nochmal den kompletten Abschnitt 7.1.3, wenn es Dir tatsaechlich darum
> geht, zu verstehen, worauf ich mich bezogen habe.
Der deckt Deine Aussage nicht und ich habe oben angeführt, das er das
nicht tut.
>> Falls man Deiner Aussage Glauben schenkt, sind bspw valgrind oder
>> libefence 'verbotene Programme' (netter Einfall,
>> wirklich). Tatsächlich sind beide aber sogar 'conforming', bloß nicht
>> 'strictly conforming'.
>
> Es geht in dieser Gruppe aussschliesslich um "strictly conforming"
> Programme, und ja, sowohl valgrind und efence sind das
> nicht. "strictly conforming" Programme sind solche, die nur Features
> verwenden, die im Standard definiert sind. Programme die bloss
> "conforming" sind koennen alles moegliche verwenden, was ein C
> Compiler so anbietet.
Die Behauptung, der C-Standard würde alles andere 'verbieten' ist
falsch.
> P.S.: Ich habe .invalid jetzt auch im Killfile. Entweder Du laesst Dir nochmal
> was neues einfallen, oder Du verwendest in Zukunft Mail fuer solche Sachen,
> wie es eigentlich am sinnvollsten waere.
Ich denke, es ist sinnvoller, wenn Du mit den öffentlichem Herumhetzen
ohne Inhalt aufhörst, denn Du wirst damit gegen eine Mauer laufen.
Wenn ich sie als Antwort auf "Unterschied zwischen einem 'Intrinsic' und
einer Standardfunktion erklären." bekomme, schon. Sonst hätte ich nach
einer Übersetzung gefragt. Aber Dir ist der Unterschied wohl nicht klar.
#> Eine Intrinsic ist also ein Satz von i386 MMX Zugriffsfunktionen in C++?
#> Kennst Du eigentlich den Unterschied zwischen einer Definition und
#> einem Beispiel?
#
# War nur ein Beispiel. Wenn dir das nicht reicht, tust du mir leid.
Wie? Du kannst nicht mal eine Defintion hier vorstellen, nachdem Du
getönt hast, die sei sogar wohldefiniert? Das ist nun wirklich schwach.
Ich nehme Dich beim Wort:
# Der Begriff taucht zwar im Standard meines Wissens nicht auf, ist aber
# dennoch weit verbreitet und wohl definiert.
Dann bitte ich um die Nennung einer solchen Wohldefinition.
Die dclc Gemeinde ist gespannt, ob Du zu Deinem Wort stehst.
...
#> Überraschung! Genau das weiß er: ISO C99 7.20.2.2 "If rand is called
#> before any calls to srand have been made, the same sequence shall be
#> generated as when srand is first called with a seed value of 1."
#> Vielleicht solltest Du Deine Annahmen prüfen, bevor Du so leicht
#> angreifbare Aussagen machst.
#
# Wobei du allerdings davon ausgehst, das der Compiler weiß, welcher Aufruf
# von rand() chronologisch der erste ist.
Ja und? Da andere Codeteile nicht explizit dastehen, beziehe ich mal auf
jene, die dastehen. Erkennst Du jetzt vielleicht die Notwendigkeit,
komplette Codebeispiele als Argument zu benutzen? Dann sind solche
Annahmen von vornherein kein Thema.
...
#> Code wie den angegebenen sollte kein Compiler optimieren können.
#> Beispiel:
#>
#> for (int i= 0; i < 1000000; ++i)
#> {
#> x = rand(3000) * i;
#> }
#>
#> Kann nicht optimiert werden, da das Ergebniss tatsächlich von der Zahl
#> der Aufrufe abhängt. Eine Optimierung wäre nur möglich, wenn der
#> Compiler exaktes Wissen über die aufgerufene Funktion hat. Das geht
#> vielleicht bei Intrinsics, aber nicht im allgemeinen.
#>
#> Nur um Deine Fantasie mal ein wenig anzukurbeln: Das obige ist trivial
#> optimierbar: Der Compiler generiert kurz den Code, führt ihn aus und
#> schaut nach dem Ergebnis in x, erzeugt dann tatsächlich nur eine
#> Instruktion x = Ergebnis. Voilà! Ist eine Form von
#> Laufzeit-Invariantenoptimierung.
#
# Die aber nur funktioniert, wenn der Compiler den gesamten chronologisch vor
# dem zu optimierenden Code
# auszuführenden Code ebenfalls "mal schnell ausführt" - was in der weitaus
# größeren Zahl aller Fälle
# undenkbar ist (insbesondere, wenn noch Benutzereingaben den Ablauf steuern).
Und? Stehen die da? Stehen die in meiner main() Funktion? Nutzen
von kompletten Beispielen mittlerweile durchgesickert?
...
#> und anders als Du kenne ich den Standard, weiß
#> welche Aussagen er zur abstrakten Maschine und zur Programmausführung
#> macht und argumentiere entsprechend.
#
# Woher willst du wissen, was ich weiß?
Deine Aussagen zu C, Optimierungsmöglichkeiten, rand, srand,
Seiteneffekten uam. lassen darauf schließen, das Du den ISO C Standard
nicht gelesen hast. Du darfst uns durch fachliche Kompetenz aber gerne
das Gegenteil beweisen. Nichts schätzen wir in dclc mehr. Von
"Intrinsics" wollen wir hier aber nix wissen :-)
>u...@remove-to-reply.musoftware.de (Ullrich von Bassewitz) writes:
>> Rainer Weikusat <a...@b.invalid> wrote:
>>> Das hast Du gerade frei erfunden.
>>
>> Sind wir wieder am staenkern, ja?
>
>Ulrich, das ist mein bitterer Ernst:
Hatte Ulrich nicht gesagt, daß Usenet das falsche Medium für sowas ist?
>Dito für Herrn Reibenstein.
Was hat /er/ denn jetzt verbrochen?
>>> If the program declares or defines an identifier in a context
>>> in which it is reserved (other than as allowed by 7.1.4), or
>>> defines a reserved identifier as a macro name, the behavior is
>>> undefined.
>>
>> Lies nochmal den kompletten Abschnitt 7.1.3, wenn es Dir tatsaechlich
>> darum geht, zu verstehen, worauf ich mich bezogen habe.
>
>Der deckt Deine Aussage nicht und ich habe oben angeführt, das er das
>nicht tut.
Klar Darf man jede x-beliebige Funktion neu schreiben. Z.B. kann man eine
eigene Funktion printf schreiben. Dummerweise darf man dann stdio.h nicht
einbinden, und dadurch wiederum kann man nichts mehr auf stdout ausgeben.
Wenn es das ist, was Du meinst, dann sag es doch gleich.
>>> Falls man Deiner Aussage Glauben schenkt, sind bspw valgrind oder
>>> libefence 'verbotene Programme' (netter Einfall,
>>> wirklich). Tatsächlich sind beide aber sogar 'conforming', bloß nicht
>>> 'strictly conforming'.
>>
>> Es geht in dieser Gruppe aussschliesslich um "strictly conforming"
>> Programme, und ja, sowohl valgrind und efence sind das
>> nicht. "strictly conforming" Programme sind solche, die nur Features
>> verwenden, die im Standard definiert sind. Programme die bloss
>> "conforming" sind koennen alles moegliche verwenden, was ein C
>> Compiler so anbietet.
Wieso verwendet Ein Programm, welches mit valgrind läuft irgendwelche
Features, die es nicht verwendet, wenn es ohne valgrind fäuft?
>Die Behauptung, der C-Standard würde alles andere 'verbieten' ist
>falsch.
Für ein strictly conforming Programm auf jeden Fall.
>> P.S.: Ich habe .invalid jetzt auch im Killfile. Entweder Du laesst Dir
>> nochmal was neues einfallen, oder Du verwendest in Zukunft Mail fuer
>> solche Sachen,wie es eigentlich am sinnvollsten waere.
>
>Ich denke, es ist sinnvoller, wenn Du mit den öffentlichem Herumhetzen
>ohne Inhalt aufhörst, denn Du wirst damit gegen eine Mauer laufen.
Nun, ich habe das Gefühl, derjenige, der am meisten gegen Dich hetzen täte
seiest Du selbst. (Man beachte den Konjunktiv.)
Gruß, Bodo
--
MS Outlook Express?->[DE: http://piology.org/ILOVEYOU-Signature-FAQ.html]
@@@@@ GEGEN TCG aka. TCPA: @@@@@ [DE: http://www.againsttcpa.com]
Probleme mit Spam? [EN: http://www.spamhaus.org/globalremove.html]
> X-Newsreader: Microsoft Outlook Express 6.00.2800.1158
Aja, ich korrigiere jetzt das Kammquoting mal per Hand.
>> Das darf er sehr wohl. Die Namen der Standard Funktionen sind
>> reserviert, koennen also nicht fuer eigene Funktionen verwendet werden.
>> Deshalb kann und darf der Compiler wissen, wie sich sqrt() verhaelt,
>> und er kann und darf den Aufruf deshalb auch wegoptimieren.
>
> Um Missverständnissen vorzubeugen: sqrt() ist ein Intrinsic, daher kann
> der Compiler die erwähnte Optimierung vornehmen (das sagte ich aber
> auch). rand() ist zwar eine Standard-Funktion und wäre nach deinem
> Statement ebenfalls optimierbar - genau das geht aber nicht, weil es
> eben _kein_ Intrinsic ist.
Schön. Gesetzt dem Fall, eine Implementation verwendet irgendeine Funktion
für die Zufallszahlenberechnung, die beliebig viele Schritte überspringen
kann, darf der Compiler dann for (i=0;i<10000;++i) test = rand(); durch
test = _rand(10000); ersetzen oder nicht?
> Daher auch mein Posting: mein VP war der Meinung, das der Compiler
> _solche_ Konstrukte immer optimieren könne.
Es ging ihm offensichtlich um Intrinsics.
> Genau das stimmt aber so nicht - lies noch einmal mein voriges Posting
> und du wirst sehen, das wir eigentlich einer Meinung sind...
Nun, der Ausgangspunkt ist ein anderer.
>> Fuer den Programmierer ist nur wichtig, dass das Programm sich so
>> verhaelt, als ob sqrt() tatsaechlich aufgerufen worden waere. Und wenn
>> der Compiler direkt das Ergebnis einsetzt, dann ist genau das
>> sichergestellt.
>
> Ack. Ist aber kein Widerspruch zu meiner Aussage.
Na, willst Du Deine Aussage nochmal überprüfen?
> Wenn ich sie als Antwort auf "Unterschied zwischen einem 'Intrinsic' und
> einer Standardfunktion erklären." bekomme, schon. Sonst hätte ich nach
> einer Übersetzung gefragt. Aber Dir ist der Unterschied wohl nicht klar.
Absolut - aber ich hätte nicht gedacht, das ein wenig selbstständige Suche
dich bereits überfordert.
> Dann bitte ich um die Nennung einer solchen Wohldefinition.
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vccelng/htm/pragm_17.asp
> Ja und? Da andere Codeteile nicht explizit dastehen, beziehe ich mal auf
> jene, die dastehen. Erkennst Du jetzt vielleicht die Notwendigkeit,
> komplette Codebeispiele als Argument zu benutzen? Dann sind solche
> Annahmen von vornherein kein Thema.
Spassvogel, es geht ums Prinzip. Es wäre ziemlicher Stuss, jedesmal ein
vollständiges Stück Code
zu posten, nur um bestimmte Dinge zu visualisieren. Aber Abstraktion scheint
dich ja reichlich zu überfordern...
> # Die aber nur funktioniert, wenn der Compiler den gesamten chronologisch
vor
> # dem zu optimierenden Code
> # auszuführenden Code ebenfalls "mal schnell ausführt" - was in der
weitaus
> # größeren Zahl aller Fälle
> # undenkbar ist (insbesondere, wenn noch Benutzereingaben den Ablauf
steuern).
>
> Und? Stehen die da? Stehen die in meiner main() Funktion? Nutzen
> von kompletten Beispielen mittlerweile durchgesickert?
In deiner main() Funktion nicht. Aber es ging mir - wie bereits gesagt - ums
Prinzip. Einen Fall
zu konstruieren, in dem bestimmte Dinge gehen, ist relativ einfach. Es geht
aber um den allgemeinen
Fall - hast du das so langsam begriffen?
> Deine Aussagen zu C, Optimierungsmöglichkeiten, rand, srand,
> Seiteneffekten uam. lassen darauf schließen, das Du den ISO C Standard
> nicht gelesen hast.
Erstens: ich habe ihn gelesen. Zweitens: selbst wenn das nicht der Fall
wäre, ist es für einen
halbwegs intelligenten Menschen recht einfach, zu erkennen, was - rein
logisch und vom Informationsgehalt her - gehen
_kann_ und was nicht. Offenbar bist du dazu nicht in der Lage.
> Du darfst uns durch fachliche Kompetenz aber gerne
> das Gegenteil beweisen. Nichts schätzen wir in dclc mehr. Von
> "Intrinsics" wollen wir hier aber nix wissen :-)
Schade - ist immer gut, wenn man weiss, was das ist.
Christian
> Stefan Reuther <sr...@inf.tu-dresden.de> writes:
>> Rainer Weikusat <weik...@students.uni-mainz.de> wrote:
>>> u...@remove-to-reply.musoftware.de (Ullrich von Bassewitz) writes:
>>>> Das einzige wo Du eventuell recht hast ist, dass es wohl keinen
>>>> Compilerbauer geben wird, der tatsaechlich Arbeit in die Optimierung
>>>> von rand() steckt.
>>
>>> gcc wird das irgendwann tun, nur keine Panik. Ansonsten stellt sich
>>> die Frage, woher der Compiler weiß, was das Programm tun sollte,
>>> inwiefern also ein anderes Programm diese Aufgabe besser erledigen
>>> könnte. Falls ich
>>
>>> a = rand();
>>
>>> schreibe und ein Compiler übersetzt das zu
>>
>>> a = 0;
>>
>>> ist das zunächst mal bloß anders.
>>
>> Das ist auch keine korrekte "Optimierung" von rand().
>
> In der Tat. Es ist ein Austauschen von Programmteilen nach Maßgabe
> einer undokumentierten Richtlinie auf der Basis von ein paar Annahmen,
> was ich 'eigentlich hätte schreiben wollen', die sich auf nichts
> gründen.
Nun, es steht Dir frei, den Compilerschalter -O in Ruhe zu lassen.
>>>> Das ist aber ein anderes Problem. Der Standard erlaubt die
>>>> Optimierung sehr wohl,
>>>
>>> Was verbessert sie denn im allgemeinen Fall?
>>
>> Es sind immerhin Verbesserungen möglich, wenn ein Programm
>> mehrere Zufallszahlen nacheinander abruft.
>
> Du hast die Frage nicht beantwortet. Woher weiß der Compiler, welcher
> Algorithmus zur Lösung eines im unbekannten Problems 'optimal' ist und
> wie ist 'optimal' in diesem Zusammenhang definiert?
Durch mehr oder weniger viele Optionen, die mit -f angangen.
>Hier geht es immerhin nicht darum, Maschinenbefehle umzuordnen, sondern
>Programmsemantik 'silently' zu ändern.
Welchen Wert erwartest Du von rand() unmittelbar nach dem Programmstart?
>Der einzige Effekt, der mir bis jetzt praktisch aufgefallen ist, ist der,
>daß mit irgendwelchen wirren und unportablen Tricks dafür sorgt, daß der
>Optimizer den Code in Ruhe läßt, weil er seine primitiven
>Analysemöglichkeiten übersteigt.
???
>>> a = time();
>>> b = rand();
>>> printf("%d\n", time() - a);
>>
>> [suspend-to-RAM-Modus, Debugger, Scheduler]
>
> Gibt es in C nicht.
Garantien über Laufzeiteigenschaften auch nicht. (Ist ein Programm, das
time() verwendet ünerhaupt strictly conforming?)
>> Oder time_t wrappt.
>
> Kann es nicht. Es ist signed, das Überlaufverhalten also undefiniert.
int inc(int wrapping_i) {
return (wrapping_i==MAX_INT)?MIN_INT:1+wrapping_i;
}
Wirklich?
>>> ergo wäre das Entfernen das Funtionsaufrufes verboten. Ich
>>> habe bewußt 'wäre' geschrieben, weil ein 'Compilerbauer' das
>>> auch nicht zwangsläufig verstehen muß, und, wie zB die
>>> 'Optimierung' von printf("string\n") zu puts("string") durch
>>> gcc zeigt, auch wahrscheinlich nicht tut.
>>
>> printf->puts ist für eine Hosted-Umgebung eine zulässige
>> Optimierung, auch wenn du tausendmal das Gegenteil behauptest.
>> Bitte Kapitel und Vers zitieren. Ich
>
>Das hatte ich bereits getan.
Wann? Wo?
>Das hier ist strictly conforming:
>
> #include <stdio.h>
> #include <time.h>
> #include <stdlib.h>
>
> int main(void)
> {
> clock_t t0;
>
> t0 = clock();
>
ein paar mal > sqrt(4);
>
> t0 = clock() - t0;
>
> return t0;
> }
>
>Den 'Unterschied' kann ich nur dann nicht festellen, falls clock() bei
>einer konkreten Implementierung immer -1 liefert. Dann dürfte man
>sowas 'optimieren'. Du darfst mich widerlegen. Und vielleicht die
>Frage beantworten, was hier eigentlich nach Maßgabe von wessen besser
>oder schlechter ist.
Wenn solch ein Programm unter anderen Laufzeitbedingungen Gestartet wird,
erhält es andere Eingangswerte (durch clock()) und darf damit andere
Ergebnisse erbringen. Damit ist es in normalen umgebungen eigentlich
unmöglich, hiermit irgendetwas bzgl. Laufzeitverhalten und Standard
beweisen zu wollen.
>"Jens Schweikhardt" <use...@schweikhardt.net> schrieb im Newsbeitrag
>news:bi2469$2n7$1...@newsfeed.pit.comms.marconi.com...
:-(
>> Eine Intrinsic ist also ein Satz von i386 MMX Zugriffsfunktionen in
>> C++? Kennst Du eigentlich den Unterschied zwischen einer Definition und
>> einem Beispiel?
>
>War nur ein Beispiel.
Es war aber eine Definition gefordert.
Wenn dir das nicht reicht, tust du mir leid.
1. Nein, das reicht nicht, und
2. Wenn hier jemand jemandem Leid tun sollte, dann bist Du der
Bemitleidenswerte
>> Schön, daß Du DOS geknickt hast. X11 hast Du offensichtlich nie
>> benutzt, denn es ist kein Betriebsystem, das nur am Rande.
>
> Weiss ich - X wird aber nur auf veralteten Betriebssystemen
Wie zum Beispiel dem von wenigen Monaten veröffentlichen Linux
Kernel 2.4.21 ... (Wie alt ist eigentlich das aktuellste Wintendo?)
> eingesetzt. Gut, es gibt ein paar Verrückte, die meinen, das auch unter
> Windows haben zu müssen...
Wieso? Dadurch wird das auch nicht stabiler.
>> Überraschung! Genau das weiß er: ISO C99 7.20.2.2 "If rand is called
>> before any calls to srand have been made, the same sequence shall be
>> generated as when srand is first called with a seed value of 1."
>> Vielleicht solltest Du Deine Annahmen prüfen, bevor Du so leicht
>> angreifbare Aussagen machst.
>
> Wobei du allerdings davon ausgehst, das der Compiler weiß, welcher
> Aufruf von rand() chronologisch der erste ist.
Darum werden hier ja vollständige Programm gefordert.
#include <stdio.h>
int main(void) {
int i,x;
for (i=0;i<100;++i)
x = rand();
printf("%i\n",x);
return i;
}
>> Unfug. Jedes Schnipsel mit Ein/Ausgabe hat solche Seiteneffekte.
>
>Ich habe kein Codefragment mit Ein-/Ausgabe gepostet...
Und damit kann das gesamte Codefragment wegoptimiert werden, denn an der
Ausgabe ändert sich exakt garnichts.
>> [Laufzeit-Invariantenoptimierung]
>
> Die aber nur funktioniert, wenn der Compiler den gesamten chronologisch
> vor dem zu optimierenden Code auszuführenden Code ebenfalls "mal schnell
> ausführt" - was in der weitaus größeren Zahl aller Fälle undenkbar ist
> (insbesondere, wenn noch Benutzereingaben den Ablauf steuern).
Dann haben wir es aber nicht mehr mit diesem Trivial-Beispiel zu tun.
>Ich habe nicht behauptet, das rand()-Sequenzen _nie_ optimierbar wären:
>das sie in trivialen Fällen optimierbar sind, will ich ja noch glauben -
>aber im Allgemeinen geht das nicht!
_rand(num_calls);
>> Welcher Compiler wann wieviel Intelligenz für Optimierungen aufwendet
>> ist ein weites Feld, das sich täglich ändert. Daher sind alle Aussagen
>> diesbezüglich prinzipiell vage. Ich spreche daher von den theoretisch
>> möglichen Optimierungen,
>
>Da sind wir ja tatsächlich mal einer Meinung...
Mit anderen Worten nimmt sich der Compiler die Quellen zu
someUnknownFunc() vor, schaut rein, was da passiert, und stellt fest, daß
es mit srand(4771) gleichgesetzt werden kann.
>> und anders als Du kenne ich den Standard, weiß
>> welche Aussagen er zur abstrakten Maschine und zur Programmausführung
>> macht und argumentiere entsprechend.
>
>Woher willst du wissen, was ich weiß?
Aus Deinen Aussagen. Ist allerdings wirklich nicht schwer.
>[Wörterbuch, Intrinsic]
>
>> Wo ist in dieser URL der Unterschied zwischen einem "Intrinsic" und
>> einer Standardfunktion erklärt?
>
> [Gar nicht, fähiger Brauser, lesen müssen]
Nun, das war nicht die Frage. Hier ist ISO C und /nur/ ISO C (ok auch ANSI
und K&R) On Topic, alles andere it Off Topic.
>> Dann bitte ich um die Nennung einer solchen Wohldefinition.
>
> http://msdn.microsoft.com/[...]
^^^^^^^^^
Seit wann ist WinzigWeich eine Normungsinstanz?
> http://www.tacc.utexas.edu/resources/user_guides/intel/c_ug/linux112.htm
Auch hier kann ich keine Normierungsinstanz erkennen
>> [intrinsics und X11]
>
> Mit veralteten Betriebsystemen muß ich mich dankenswerterweise nicht
> mehr befassen.
Du willst also einen Flame anfangen? Kannst Du haben.
Du bezeichnest also X11 als ein Betriebssystem?
[X] Du redest von Dingen, von denen Du keine Ahnung hast
[X] Du möchtest Dich über die Unix Umgebung informieren,
insbesondere über Linux
[X] Du wirst irgendwann auch mal feststellen, daß Linux stabiler und
sicherer ist als Windows
[X] Du wirst feststellen, daß Linux erst Ende der 80er Jahre engefangen
wurde, also zu einer Zeit, als schon Millionen Rechner weltweit mit
Windows permanent abstürzten.
Wenn Du noch mehr hören möchstest, kannst Du mir in de.alt.flame
antworten, x-post habe ich schonmal gemacht, fup2 habe ich mit gespart,
vielleicht willst Du ja doch keinen Flame ...
>> Doch. Z.B. könnte der Compiler den seed so wählen, daß einfach der 10.
>> Wert für rand() als nächstes erscheint.
>
> Sicher, wenn er denn wüßte, was der 10. Wert für rand() ist.
Dafür ist er der Compiler (der teil der Implementation ist).
> Und dazu müßte er den seed, der beim ersten Aufruf gerade vorliegt,
> kennen...
0, hast Du doch da selber hingeschrieben.
>> Darüberhinaus hat dein Codeschnipsel *überhauptkeinen* Effekt und
>> könnte vollständig entfernt werden. Also ist es besser, wenn wir uns in
>> dieser Diskussion auf vollständige Programme inklusive Seiteneffekten
>> wie Ausgabe konzentrieren.
>
> Das ist ja nun wirklich Unfug: jedes Codefragment, das man zu dieser
> Diskussion hier posten würde, hätte für sich alleine keinen Nutzeffekt
> und könnte vollständig eleminiert werden.
Es ist schon wichtig zu wissen, für was man dich interessiert.
int func() {
int i,x;
for (i=x=0;i<100000;++i) {
++x;
}
return x;
}
Beispiel 1:
int main(void) {
return func()-func();
}
> Sich auf "vollständige Programme" zu konzentrieren ist erst Recht
> Quatsch: Es soll ja Leute geben, die Libs basteln; die haben überhaupt
> keine vollständigen Programme, an denen sie untersuchen könnten!
Beispiel 2:
int main(void) {
return func();
}
>> #include <stdio.h>
>> #include <stdlib.h>
>>
>> int main (void)
>> {
>> int x;
>>
>> srand (0);
>> for (i = 0; i < 10; ++i)
>> x = rand ();
>> printf ("%d\n", x);
>> return 0;
>> }
>>
>> kann sehr wohl zu jedem Programm optimiert werden, das äquivalent zu
>> puts ("42"); ist, wenn der 10. rand() 42 liefert.
>
> Ich habe nie etwas anderes behauptet!
Ach?
>Aber:
>
>#include <stdio.h>
>#include <stdlib.h>
>#include "someUnknownFunc.h"
>
>void setSeed(int s)
>{
> seed(s * rand());
>}
>
>int test10()
>{
> int x;
> for (i = 0; i < 10; ++i)
> x = rand ();
> return x;
>}
>
>int main (void)
>{
> someUnknownFunc(); // Diese Funktion möge in irgendeiner Lib liegen
> // und irgendetwas machen wie z.B. gar nichts;
> // seed() aufrufen, rand() aufrufern oder sonst
> // etwas.
Nun, wenn es eine Lib-Funktion ist, die zur Implementation gehört, weiß
der Compiler, was da geschieht, und wenn nicht, dann haben wir es hier
wohl mit einer Translation Unit zu tun, die keine Information aus anderen
Translation Units hat. Aber sowas war nie Gegenstand der Diskussion.
> setSeed(test10());
setSeed(_rand(10));
> setSeed(test10());
setSeed(_rand(10));
> printf ("%d\n", x);
undefined symbol `x'
> return 0;
>}
>
> kann nicht optimiert werden!
s/optimiert/compiliert/
> Dem Compiler würden für jedwede Optimierung bzgl. der Funktion test10()
> Informationen fehlen.
Wie das? Also ich optimiere das.
> Darum ging es beim OP: wann kann ein Compiler optimieren und wann wird
> er es tun?
Der Compiler kann immer dann optimieren, wenn das resultierende Programm
bei gleichen Eingabewerte das gleiche Ergebnis leifert, wie ein Programm,
daß streng nach dem ISO C standard ausgeführt wird.
Der Compiler wird es immer dann tun, wenn die Entwickler des gleichen den
Aufwand für die jeweilige Optimierung als geringer als den Nutzen
einschätzen.
> Den zweiten Teil der Frage kann man sowieso nicht allgemeingültig
> beantworten (da Compilerabhängig),
Komisch, habe ich gerade gemacht.
> und beim ersten Teil ist es auch interessant zu wissen, wann nicht
> optimiert werden kann.
Darüber habe ich gerade auch eine Aussage getroffen.
> Und das Beispiel zeigt, das es selbst bei Standard-C-Funktionen möglich
> ist, das der Compiler keine Optimierung ausführen kann.
Wie gesagt: _rand(10);
> Das aber hast du behauptet.
Nunja, Du wechselst immer die Beispiele, und implizierst die für die
vorhergehenden Beispiele genannten Aussagen auf Deine neuen Beispiele, und
beweist dann die Falschheit der Aussagen. Naja...
> Richtig ist: nur bei Standard-C-Funktionen _kann_ der Compiler die
> Informationen haben, die er für eine Optimierung bräuchte; aber im
> Allgemeinen _hat_ er sie einfach nicht.
Das weißt Du doch garnicht. Solange ein stricktly conforming Programm den
Unterschied nicht feststellen kann, könnte der Compiler sogar in Deinem
Beispiel beigehen, den test10() einfach durch einen rand()-Aufruf
ersetzen. Dein strictly conforming Programm wird garkeinen Unterschied
feststellen. Weil es bei jedem Lauf die gleiche Zufallszahl bekommt.
Allerdings nicht die 10te und 20te sondern die 1te und 2te, aber das weiß
das Programm ja eh nicht.
>"Jens Schweikhardt" <use...@schweikhardt.net> schrieb im Newsbeitrag
>news:bi01om$mh$1...@newsfeed.pit.comms.marconi.com...
:-(
>> [Intrinsic]
>
>http://dict.leo.org/?search=intrinsic&searchLoc=0&relink=on&spellToler=s
>td§Hdr=on&tableBorder=1&cmpType=relaxed&lang=de
Ist es eigentlich zu viel verlangt, in de de zu sprechen?
>> Ein Compiler darf sehr wohl rand()
>> wegoptimieren, auch wenn es mehrfach aufgerufen wird. Einzig
>> entscheidend ist, ob ein strikt konformes Programm den Unterschied
>> feststellen könnte.
>
>Da die Codesequenzen
>
>srand(0);
>for (i = 0; i < 10; ++i)
> x = rand();
Das wird bei mir zu srand(0); x=rand(10); i=10;
>und
>
>srand(0);
>x = rand();
>x = rand();
>x = rand();
>x = rand();
>x = rand();
>x = rand();
>x = rand();
>x = rand();
>x = rand();
>x = rand();
Wird bei mir zu srand(0); x=rand(10);
>dann bei Optimierung der for-Schleife ein unterschiedliches Ergebniss
>liefern würden, würde ein jedes Programm,
>das derartigen Code enthält, den Unterschied feststellen können.
Das Programm könnte den Unerschied nicht feststellen, weil es bei mir
keinen Unterschied gibt.
>Ergo läßt sich die for-Schleife nicht optimieren.
Noch nie was von der as-if-Regel gehört?
>War doch nicht schwer und hat gar nicht weh getan - oder?
Nunja, die Frage gebe ich dann mal unverändert zurück.
>"Jens Schweikhardt" <use...@schweikhardt.net> schrieb im Newsbeitrag
>news:bi2cal$2tu$1...@newsfeed.pit.comms.marconi.com...
:-(
>> Dann bitte ich um die Nennung einer solchen Wohldefinition.
>
>http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vccelng
>/htm/pragm_17.asp
Microsoft ist immernoch keine Normungsinstanz
>Aber Abstraktion scheint dich ja reichlich zu überfordern...
Mein gcc übersetzt keine abstrakten Codes. Alles was ich gcc gebe sind
konkrete C statements. Und das kann er optimieren, mehr oder weniger gut.
Genauso wie Du hier ankommst von wegen Code-Schnipsel, könnte ich Dich
fragen, ob f=sqrt(g); optimiert werden kann oder nicht. Und? kann es?
> Einen Fall zu konstruieren, in dem bestimmte Dinge gehen, ist relativ
> einfach. Esgeht aber um den allgemeinen Fall - hast du das so langsam
> begriffen?
Hast Du es so langsam begriffem daß Compier keinen abstrakten Code
übersetzen?
>> Deine Aussagen zu C, Optimierungsmöglichkeiten, rand, srand,
>> Seiteneffekten uam. lassen darauf schließen, das Du den ISO C Standard
>> nicht gelesen hast.
>
> Erstens: ich habe ihn gelesen.
Auch verstanden?
> Zweitens: selbst wenn das nicht der Fall wäre,
oh, wird da etwa die Flucht vorbereitet?
> ist es für einen halbwegs intelligenten Menschen recht einfach, zu
> erkennen, was - rein logisch und vom Informationsgehalt her - gehen
> _kann_ und was nicht.
Klar, wir sprechen aber in dieser Gruppe nicht über logischen
Menschenverstand, sonden über ISO C.
>Offenbar bist du dazu nicht in der Lage.
Dazu sind hier fast alle in der Lage. Aber Du bist nicht in der Lage, zu
erkennen, was hier Thema ist, und was nicht.
>> Du darfst uns durch fachliche Kompetenz aber gerne
>> das Gegenteil beweisen. Nichts schätzen wir in dclc mehr. Von
>> "Intrinsics" wollen wir hier aber nix wissen :-)
>
> Schade - ist immer gut, wenn man weiss, was das ist.
Wie Winzigweich irgendwelche Optimierungsversuche durch ihren C/C++
Compiler realisieren, interessiert hier erstmal maximal nebensächlich.
>Wenn Du noch mehr hören möchstest, kannst Du mir in de.alt.flame
>antworten, x-post habe ich schonmal gemacht,
Ok, irgendwie habe ich das dann wohl vergessen, in die Tat umzusetzen,
einfach in de.alt.flame antworten (meinetwegen auch mit x-post).
time() selber ist strictly conforming, aber mit dem Rueckgabewert zu rechnen
nicht. D.h.
printf ("%d", time() - a);
wie im Beispiel hat gleich zwei Probleme: Neben dem %d (das bereits
angesprochen wurde), ist die Subtraktion unzulaessig, weil time_t kein
arithmetischer Typ sein muss. Aus dem Grund gibt es im Standard auch die
Funktion difftime(), die zum Rechnen mit time_t da ist.
POSIX macht bzgl. time_t strengere Auflagen, d.h. in POSIX konformen
Umgebungen kann man time_t auch rechnen, aber fuer d.c.l.c interessiert POSIX
natuerlich nicht.
Gruss
Uz
--
Ullrich von Bassewitz u...@remove-to-reply.musoftware.de
5:07pm up 196 days, 23:53, 69 users, load average: 0.03, 0.34, 0.43
X11 ist im Gegensatz zu z.B. Windows ein "Netzwerktransparentes" Window-
System und hat daher Vorteile. Es wird auch auf durchaus sehr modernen
Systemen eingesetzt und keineswegs nur auf veralteten. Gnu Hurd ist
IMHO genausowenig veraltet wie MacOS X, Solaris9 oder einige andere
Systeme auf denen X produktiv eingesetzt wird (auf MacOS X wird zwar
per Default ein anderes Window-System eingesetzt, dass ebenfalls nicht
netzwerktransparent arbeitet, aber X11 ist dort auch nicht so exotisch
wie du uns Glauben machen willst).
>> ?berraschung! Genau das wei? er: ISO C99 7.20.2.2 "If rand is called
>> before any calls to srand have been made, the same sequence shall be
>> generated as when srand is first called with a seed value of 1."
>> Vielleicht solltest Du Deine Annahmen pr?fen, bevor Du so leicht
>> angreifbare Aussagen machst.
> Wobei du allerdings davon ausgehst, das der Compiler wei?, welcher Aufruf
> von rand()
> chronologisch der erste ist.
Das muss er nicht, wenn er auf eine "interne" Variable mit dem aktuellen
Seed zugreifen koennte. Dem Hersteller eines Entwicklungssystems steht
es frei, dem Compiler einen solchen Zugriff auf eine interne Variable
der Library zu ermoeglichen ...
[ rand() in Schleife ]
>> Nur um Deine Fantasie mal ein wenig anzukurbeln: Das obige ist trivial
>> optimierbar: Der Compiler generiert kurz den Code, f?hrt ihn aus und
>> schaut nach dem Ergebnis in x, erzeugt dann tats?chlich nur eine
>> Instruktion x = Ergebnis. Voil?! Ist eine Form von
>> Laufzeit-Invariantenoptimierung.
> Die aber nur funktioniert, wenn der Compiler den gesamten chronologisch vor
> dem zu optimierenden Code
Nein, er muss nur den aktuellen Seed zu Beginn der Schleife kennen.
Ein "mitprotokollieren aller rand() Aufrufe" waere eine Moeglichkeit das
zu erreichen, den Zugriff auf den aktuellen Seed ermoeglichen eine weitere.
Wenn Compiler und Library vom selben Hersteller stammen, wuesste ich nicht,
warum letzteres nicht moeglich sein sollte ...
> Ich habe nicht behauptet, das rand()-Sequenzen _nie_ optimierbar w?ren: das
> sie in trivialen F?llen
> optimierbar sind, will ich ja noch glauben - aber im Allgemeinen geht das
> nicht!
Es sind standardkonforme Umgebungen denkbar, in denen deine Aussage in
dieser Pauschalitaet falsch ist. Das wurde dir mittlerweile mehr als
einmal erklaert.
Tschuess,
Juergen Ilse (jue...@usenet-verwaltung.de)
--
[ Alfred Schulze ueber Norton Internet Security in dcsf ]
Es ist ja eigentlich auch nicht zum runterbekommen gemacht.
Normalerweise gehoert es genau wie ein Windows ein Leben
lang auf den Computer.
"Christian Jan?en" <c...@christian-janszen.de> wrote:
> "Jens Schweikhardt" <use...@schweikhardt.net> schrieb:
[intrinsic ]
>> Dann bitte ich um die Nennung einer solchen Wohldefinition.
> http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vccelng/htm/pragm_17.asp
Das ist keine "Wohldefinition fuer den Begriff intrinsic im Zusammenhang
mit der Sprache C" sondern die Beschreibung der compiler-spezifischen
Direktive "#prgma intrinsic", also etwas voellig anderes, und dass der
Begriff "intrinsic" im Zusammenhang mit der Sprache C im allegemeinen in
irgend einer Weise "gebraeuchlich" waere, konntest du auch noch nicht
belegen ...
Es gibt Leute, die dich wegen solcher Dinge als "Schwaetzer" betiteln
wuerden.
>> Deine Aussagen zu C, Optimierungsm?glichkeiten, rand, srand,
>> Seiteneffekten uam. lassen darauf schlie?en, das Du den ISO C Standard
>> nicht gelesen hast.
> Erstens: ich habe ihn gelesen. Zweitens: selbst wenn das nicht der Fall
> w?re, ist es f?r einen
> halbwegs intelligenten Menschen recht einfach, zu erkennen, was - rein
> logisch und vom Informationsgehalt her - gehen
> _kann_ und was nicht. Offenbar bist du dazu nicht in der Lage.
Offenbar bist eher *du* dazu nicht in der Lage, denn deine Schlussfolgerung
ist fuer die Funktion rand() falsch, denn der Compiler darf laut Standard
zum Uebersetzungszeitpunkt beliebige Informationen ueber Implementations-
details der Standard-Library kennen, bei rand() und srand() z.B. auch eine
evt. vorhandene Moeglichkeit den aktuellen seed abzufragen. Wenn er das
koennte (was laut Standard nicht sicher ausgeschlossen werden kann),
zerfaellt dein Argumentationsgebaeude bzgl. dieser Funktionen zu *nichts*.
> Rainer Weikusat <weik...@students.uni-mainz.de> wrote:
>
>> Dito für Herrn Reibenstein.
Um was geht's eigentlich? Ich sehe die Nachrichten von Rainer nicht,
also seid so lieb und klärt mich auf.
> Was hat /er/ denn jetzt verbrochen?
Na, da bin ich aber gespannt :-)
Gruß. Claus
> X wird aber nur auf veralteten Betriebssystemen eingesetzt.
Hört, hört! Linux ist ein veraltetes Betriebssystem! Wer hätte das gedacht!
Vorsicht, Glatteis!
Gruß. Claus
> time() selber ist strictly conforming, aber mit dem Rueckgabewert zu rechnen
> nicht. D.h.
>
> printf ("%d", time() - a);
>
> wie im Beispiel hat gleich zwei Probleme: Neben dem %d (das bereits
> angesprochen wurde), ist die Subtraktion unzulaessig, weil time_t kein
> arithmetischer Typ sein muss.
Doch.
> Aus dem Grund gibt es im Standard auch die Funktion difftime(), die
> zum Rechnen mit time_t da ist.
difftime liefert die Differenz in Sekunden. Bei der einfachen
Subtraktion ist die Einheit nicht bekannt. Außerdem kann man einen
double leicht mit printf ausgeben.
Stimmt, mein Fehler (7.23.1).
Gruss
Uz
--
Ullrich von Bassewitz u...@remove-to-reply.musoftware.de
6:46pm up 197 days, 1:31, 69 users, load average: 0.08, 0.29, 0.29
Alexander Bartolich <alexander...@gmx.at> wrote:
> begin Ullrich von Bassewitz:
>> [...] Die Namen der Standard Funktionen sind reserviert,
>> koennen also nicht fuer eigene Funktionen verwendet werden.
> Man kann sehr wohl.
... nur waere das dann nicht mehr vom Standard gedeckt, es wuerde sich
nicht um ein "strictly conforming" Programm in einem "hosted Environment"
handeln. Da es in dieser Gruppe um den Standard und nicht um moegliche
Erweiterungen geht, gilt im Rahmen dieser Gruppe (von "Freestanding
Implementations" einmal abgesehen) "Die Namen der Standard Funktionen sind
reserviert und koennen nicht fuer eigene Funktionen genutzt werden, ohne
dass damit die Diskussion *hier* OffTopic wuerde".
> Ansonsten könnten die Funktion selber nicht in C implementiert werden.
Das muessen sie ja auch nicht. Niemand verlangt, dass die C-Library
in C geschrieben ist (obwohl das oftmals doch der Fall sein wird).
> Oder auch andersrum: Wenn die glibc dafür ein magisches #pragma
> brauchen würde, dann könnte auch jedes andere Programm dieses #pragma
> verwenden.
... und es wuerde damit den festen Boden des Standards (und damit das i
Thema dieser Newsgroup) verlassen, waere dann hier also OffTopic.
>> [...] Fuer den Programmierer ist nur wichtig, dass das Programm sich
>> so verhaelt, als ob sqrt() tatsaechlich aufgerufen worden waere.
> Und woher soll der Compiler wissen, ob der Programmierer da nicht
> gerade einen Benchmark schreibt?
Das kann er nicht, genauso, wie sich der Programmierer nicht sicher sein
kann, dass moeglicherweise sein "Benchmark" durch clevere Optimierungen
des Compilers ausgehebelt wird ...
"Christian Jan?en" <c...@christian-janszen.de> wrote:
> "Roland Damm" <rolan...@arcor.de> schrieb im Newsbeitrag
> news:3f434...@news.arcor-ip.de...
>> Ich denke jeder vern?nftige Compiler tut das automatisch,
>> zumindest wenn man ihm eine Optimierung einschaltet. Aber im
>> Extremfall passiert noch mehr, eventuell merkt der Compiler
>> sogar, da? das Durvchlaufen der Schleife gar nicht n?tig ist,
>> um das Endergebnis zu erhlaten. In diesem Beispiel k?nnte der
>> Compiler also den Code einfach durch zwei Zuweisungen f?r i
>> und test ersetzen. Will man das nicht, z.B. weil man eine
>> Warteschleife braucht (nicht sch?n, aber wer wei?) mu? man die
>> Optimierung des Compilers abschalten.
> Code wie den angegebenen sollte kein Compiler optimieren k?nnen.
Doch, wenn er weiss, dass die in der Schleife aufgerufene Funktion
"nebenwirkungsfrei" ist.
> Beispiel:
> for (int i= 0; i < 1000000; ++i)
> {
> x = rand(3000) * i;
> }
rand() ist vermutlich *nicht* nebenwirkungsfrei, sqrt() dagegen schon.
Da es sich bei sqrt() um eine Funktion aus der Standardlibrary handelt,
kann der Compiler das auch wissen. Wenn er es weiss, darf er an dieser
Stelle optimieren (wenn dort ein sqrt() statt rand() aufgerufen wuerde).
> Eine Optimierung w?re nur m?glich, wenn der Compiler exaktes Wissen ?ber die
> aufgerufene
> Funktion hat. Das geht vielleicht bei Intrinsics, aber nicht im allgemeinen.
Es war in der Ursprungsfrage die Rede von der Funktion sqrt(), und ueber
die kann der Compiler das wissen, da es sich um eine Funktion der Standard-
library handelt.
Uhh, und wer hat das jemals bestritten? Jeder Standard und seine
Implementierungen sind notwendigerweise verschiedene Dinge, oder
nicht?
> Es steht einer Implementierung (oder in diesem Fall einer
> Familie von Implementierungen, nämlich 'C überall außer auf
> embedded') vollkommen frei, für laut ISO undefinierte
> Situationen ein dokumentiertes Verhalten zu haben. Bei einem
> 'üblichen' Compiler-Assembler-Linker-Arrangement sollte die
> Funktion aufgerufen werden, die zuerst gefunden wird, denn man
> möchte ja auch Bibliotheksfunktionen *in eigenem Code* ersetzen
> können.
Klar kann eine Implementierung das machen aber *das hat nichts mit
dem Standard zu tun*. Der Standard erlaubt einer Implementierung
sowas (nicht dass er es praktisch verbieten koennte), aber es ist
eben ausserhalb des von ihm beschriebenen Gebietes also geht es
ihn nix an.
> > # Ansonsten könnten die Funktion selber nicht in C
> > implementiert werden.
> >
> > Doch, wenn man den Unterschied zwischen Implementierer und Anwender
> > kennt.
>
> Der zB darin besteht, das vendor X, Y und Z dafür sorgen, daß der
> Standard so aussieht, daß seine Implementierung nicht dagegen
> verstößt, obwohl sie sich nicht an die Regel hält, die für 'crethi und
> plethi' angeblich gelten sollen.
X, Y und Z sind Implementierer, fuer die koennen die Regeln gar
nicht gelten. Erklaer mal wie man z.B. fopen(), fread(), ... mit
Mitteln des Standards implementieren wuerde.
Warum hast Du denn nicht dafuer gesorgt dass der Standard so
ausssieht wie Du ihn gerne haettest? Ist AFAIK nicht ganz
unmoeglich.
> Das funktioniert ähnlich wie xdr: Wir nehmen das native Format
> unseres Systems und stellen Code, der vorwärts und rückwärts
> konvertiert, kostenlos zur Verfügung, dessen Verwendung die
> ganzen depperten Manager natürlich bevorzugen würden (weniger
> Arbeit!!1) und lachen uns tot darüber, daß wir uns gerade einen
> inhärenten Wettberwerbsvorteil 'herbeigezaubert' haben.
Oha!
Du hast also die Loesung fuer das Problem dass man fuer ein
"over-the-wire" Protokoll irgendwelche Datendarstellungen
festlegen muss? Bwahahaha!
Was ist das naechste, schmeissen wir IP weg weil es Little Endian
benutzt? MPEG auch?
Welche Darstellung waere denn politisch korrekt? NUXI? XUNI? Alles
in ASCII? Irgendwas was keine existierende Hardware tut und wir
verbieten dass zukuenftige Hardware das benutzt?
> Falls irgendein Kommitee der Meinung ist, ich solle mich
> gefälligst zugunsten von Sun, Mickeysoft, HP etc umständlicher
> ausdrücken, als das sinnvoll wäre, ist das Pech für dieses
> Kommitee.
Bloederweise hast Du damit die heute am weitesten verbreiteten
Formate von Binaerdaten ausgeschlossen. Was ist die Alternative?
> > #> Deshalb kann und darf der Compiler wissen, wie sich sqrt()
> > verhaelt, # # Any feature that cannot be turned off is a bug.
> >
> > Any statement of the form "X is the one true Y" is false.
>
> Falls die Aussage korret ist, 'beweist' sie, daß C für
> hardwarenahe Programmierung nicht zu gebrauchen ist,
Standard C ist dafuer definitiv nicht zu gebrauchen, aus dem
simplen Grund das im Standard Hardware garnicht vorkommt. Keine
Ports, keine physischen RAM-Adressen, keine IRQs, nichts
dergleichen.
> denn man kann nicht warten, weil es dem Compiler freisteht, jede
> Zeitverzögerung transparent zu ignorieren.
Was fuer eine Zeitverzoegerung? Du hast wohl von den Bugs (z.B. in
Borlands TP-Runtime AFAIR) nichts gehoert die durch so einen Unfug
kamen?
Prozessoren werden schneller. Zeitverzoegerungen durch Schleifen
sind einfach ein Bug, vielleicht z.Z. bloss ein latenter...
> Aus naheliegenden Gründen begünstigt das Leute, die immer noch
> am liebsten alles in Assembler schreiben würden und ist mir zB
> vollkommen egal. Falls der Standard nicht imstande ist, ein
> brauchbares Verhalten zu definieren, hat das Gremium versagt und
> nicht der Mensch, der dessen Hinweise notgedrungen ignoriert.
Definiere brauchbares Verhalten fuer die Sprache C. Jegliche
nachvollziehbare Kritik an Deinem Vorschlag bedeutet, dass Du
versagt hast, genau wie das Gremium.
Du hast keine Chance (nicht Du persoenlich, keiner hat da eine
Chance).
[snip]
MGri
--
Mathias Grimmberger <mg...@zaphod.sax.de>
Eat flaming death, evil Micro$oft mongrels!
Die Leute, die hier ständig Märchen erzählen, tun das in einem
fort. Dazu gehören alle diese schönen Beispiele wie zB 'der Compiler
dürfte auch das Terminal in ein gelbes Warzenschwein verwandeln'. Das
ist inhaltlich dieselbe Aussage wie 'Implementierung X verhält sich
unter folgenden Umständen: ... wie folgt: ...', lediglich ohne
Implementierung. Im C-Standard kommen keine gelben Warzenschweine vor,
sondern er legt nur bestimmte Dinge nicht fest. Nichts weiter.
>> Es steht einer Implementierung (oder in diesem Fall einer
>> Familie von Implementierungen, nämlich 'C überall außer auf
>> embedded') vollkommen frei, für laut ISO undefinierte
>> Situationen ein dokumentiertes Verhalten zu haben. Bei einem
>> 'üblichen' Compiler-Assembler-Linker-Arrangement sollte die
>> Funktion aufgerufen werden, die zuerst gefunden wird, denn man
>> möchte ja auch Bibliotheksfunktionen *in eigenem Code* ersetzen
>> können.
>
> Klar kann eine Implementierung das machen aber *das hat nichts mit
> dem Standard zu tun*. Der Standard erlaubt einer Implementierung
> sowas (nicht dass er es praktisch verbieten koennte), aber es ist
> eben ausserhalb des von ihm beschriebenen Gebietes also geht es
> ihn nix an.
Ergo ist die Ausage 'X wird durch den C-Standard verboten' dann
falsch, wenn es um syntaktisch und grammatikalisch korrekte
Formulierungen geht, deren Semantik nicht standardisiert ist.
++i = i++
ist vollkommen 'legales' C, bloß hängt es von der Implementierung ab,
in welcher Reihenfolge die Seiteneffekte wirksam werden. Es bedeutet
nicht, daß eine Übersetzung, die nach C rückübersetzt, so aussähe:
i = sqrt(3.14) - 3177; /* whatever */
ein akzeptables Compilerverhalten wäre und das wird deswegen nicht
explizit verboten, weil jemand, der wenigstens eine minimale
Vorstellung davon hat, wie ein Computerprogramm arbeitet, sich darüber
im Klaren ist, das man diesen Sonderfall gezielt abfangen und
absichtlich anders behandeln müßte, als
++i;
i = ++i;
und zwar auschließlich deswegen, weil man jemanden gezielt in den
Arsch treten möchte. Die Leute, die solchen Unsinn propagieren, sollen
bitte Compiler schreiben, die sich so verhalten, und dann man
abwarten, welche Marktdurchdringung die unter Berücksichtigung von
'quality of implementation' erreichen. Mutmaßlich keine, was
ausdrücklich konform zur Intention des C-Standards ist. Falls reale
Implementierungen von C hier nicht erwünscht sind, fällt es mir leider
schwer, zu verstehen, warum das für fiktionale Implementierung nicht
auch gilt.
>> Der zB darin besteht, das vendor X, Y und Z dafür sorgen, daß der
>> Standard so aussieht, daß seine Implementierung nicht dagegen
>> verstößt, obwohl sie sich nicht an die Regel hält, die für 'crethi und
>> plethi' angeblich gelten sollen.
>
> X, Y und Z sind Implementierer, fuer die koennen die Regeln gar
> nicht gelten. Erklaer mal wie man z.B. fopen(), fread(), ... mit
> Mitteln des Standards implementieren wuerde.
Das war der Punkt. C ist in vielen Bereichen absichtlich vage, um
unterschiedliche Implementierungen zu gestatten. Nicht deswegen, damit
die Leute, die außer ihrem eigenen Geschwätz an nichts glauben,
solche, die vielleicht etwas lernen möchten, mit maximalem Schwachsinn
verwirren können.
> Warum hast Du denn nicht dafuer gesorgt dass der Standard so
> ausssieht wie Du ihn gerne haettest? Ist AFAIK nicht ganz
> unmoeglich.
Der C-Standard selber ist nicht annähernd so wahnsinnig, wie er hier
gerne von Leuten, denen scheinbar das Hintergrundwissen fehlt, um ihn
zu verstehen, gerne interpretiert wird. Er richtet sich lediglich an
ein Publikum von Leuten, die C programmiert haben, bevor es genormt
wurde (zu dem ich mich auch nicht wirklich zählen kann. Aber ich gebe
mir wenigstens Mühe, das zu verstehen, anstelle es mit terroristischer
Kreativtät zu entstellen).
>> Das funktioniert ähnlich wie xdr: Wir nehmen das native Format
>> unseres Systems und stellen Code, der vorwärts und rückwärts
>> konvertiert, kostenlos zur Verfügung, dessen Verwendung die
>> ganzen depperten Manager natürlich bevorzugen würden (weniger
>> Arbeit!!1) und lachen uns tot darüber, daß wir uns gerade einen
>> inhärenten Wettberwerbsvorteil 'herbeigezaubert' haben.
>
> Oha!
>
> Du hast also die Loesung fuer das Problem dass man fuer ein
> "over-the-wire" Protokoll irgendwelche Datendarstellungen
> festlegen muss? Bwahahaha!
Nein, ich 'habe' die nicht, aber OSF DCE-RPC hatte mal eine, nämlich
das Datenformat ebenfalls zu kommunizieren, damit Konversionen nur
dann durchgeführt werden müssen, wenn sie tatsächlich notwendig sind:
For instance, consider two VAX-11 machines using a protocol
that relies on XDR encoding. Since the VAX is little endian
([...]), the sender would have to convert each integer to
big-endian form (mandated by XDR), and the receiver would have
to convert it back to little-endian form. This wasteful
exercise could be prevented if the representation some means
of communicatin the machine characteristics, so that
conversions where only required for unlikely machines.
[UNIX Internal, p. 299/300]
In short garantiert das, das Sun-Rechner (traditionell big-endian)
immer einen höheren NFS-Durchsatz erzielen werden, als andere, was den
Erfindern dieser Repräsentation nicht ganz unlieb gewesen sein
dürfte. Deswegen auch der nette Trick mit der RPC-Bibliothek (und es
ist natürlich auch ganz praktisch, Teile der Weiterentwicklungskosten
an Dritte abzutreten, die den Schrott mehr oder minder unfreiwillig
benutzen müssen). 'Bait & switch', ziemlich klassisch.
> Was ist das naechste, schmeissen wir IP weg weil es Little Endian
> benutzt?
<nitpick>
big endian
</>
> MPEG auch?
MPEG in jedem Fall. »Leider war unser erste Entwurf vollkommener
Bullshit, deswegen definieren wir den alten Header als konstant und
die 'echten Daten' stehen im Erweiterungsheader dahinter«, aka »This
bit is here for historical reasons and shall have the value one«.
Das ist übrigens dasselbe Verfahren: Wir definieren ein
schwachsinniges Datenformat und stellen eine grottige
Referenzimplementierung kostenlos zur Verfügung, wodurch wir uns ein
ewiges Einkommen via royalties von den Leuten, die unseren Abfall in
einen funktionsfähigen Zustand überführen sollen, sichern.
> Welche Darstellung waere denn politisch korrekt? NUXI? XUNI? Alles
> in ASCII? Irgendwas was keine existierende Hardware tut und wir
> verbieten dass zukuenftige Hardware das benutzt?
Um aufs topic zurückzukommen: C-Stringfunktionen heißen normalerweise
strirgendwas. Falls ich mit drei Systemen zu tun habe, von denen zwei
eine Funktion namens 'strlcpy' bieten, mag ich nicht einsehen, warum
ich das im Code so behandeln sollte:
#if !defined(linux)
# define bounded_buffer_string_copy strlcpy
#else
char *bounded_buffer_string_copy(char *d, char const *s, size_t l)
{
.
.
.
}
#endif
falls ich an 'maximaler Portabilität', aka 'läuft auf jedem Toaster'
gar nicht interessiert bin. Das ist nicht 'falsch', sondern bloß nicht
auf alle denkbaren C-Implementierungen portabel (und vermutlich auch
auf ein paar reale nicht). Es ist das auch nicht versehentlich,
sondern mit voller Absicht.
>> Falls irgendein Kommitee der Meinung ist, ich solle mich
>> gefälligst zugunsten von Sun, Mickeysoft, HP etc umständlicher
>> ausdrücken, als das sinnvoll wäre, ist das Pech für dieses
>> Kommitee.
>
> Bloederweise hast Du damit die heute am weitesten verbreiteten
> Formate von Binaerdaten ausgeschlossen. Was ist die Alternative?
Du hast den Bezug mißverstanden, s.o.
>> Falls die Aussage korret ist, 'beweist' sie, daß C für
>> hardwarenahe Programmierung nicht zu gebrauchen ist,
>
> Standard C ist dafuer definitiv nicht zu gebrauchen, aus dem
> simplen Grund das im Standard Hardware garnicht vorkommt. Keine
> Ports, keine physischen RAM-Adressen, keine IRQs, nichts
> dergleichen.
Nein, FORTRAN ist dafür nicht zu gebrauchen, denn es hat ein
vollkommen anderes Einsatzgebiet. C ist nicht 'FORTRAN für Doofe',
sondern eine maschinennahe Sprache. Der Sinn von sowas ist nicht, daß
man rasend schnell ablaufende Programme schreiben kann, sondern, daß
man *maschinennah* damit programmieren kann, was für bestimmte
Aufgaben notwendig und für andere sinnvoll ist.
>> denn man kann nicht warten, weil es dem Compiler freisteht, jede
>> Zeitverzögerung transparent zu ignorieren.
>
> Was fuer eine Zeitverzoegerung? Du hast wohl von den Bugs (z.B. in
> Borlands TP-Runtime AFAIR) nichts gehoert die durch so einen Unfug
> kamen?
Ähh ... ich weiß nicht, ob das jetzt konkret auf mich zurückgeht, aber
diesen Fehler hatte ich irgendwann mal für meinen Vater behoben und
das vor einer nicht allzulangen Zeit in einem anderen Kontext auch mal
gepostet ...
> Prozessoren werden schneller. Zeitverzoegerungen durch Schleifen
> sind einfach ein Bug, vielleicht z.Z. bloss ein latenter...
[rw@winter]:~ $cat /proc/cpuinfo
processor : 0
vendor_id : AuthenticAMD
cpu family : 6
model : 4
model name : AMD Athlon(tm) Processor
[...]
bogomips : 1395.91
Ich kann mich erinnern, das das schon weniger waren. Der Code dazu ist
durchaus lesenswert, unter anderem deswegen, weil er beleuchtet, wie
vollkommen sinnlos Kommentare für das Verständnis von Quelltexten sind
(das mag anderen Leuten evtl anders ergehen, aber nachdem ich die
Funktion verstanden hatte, war mir auch der Sinn der Kommentare klar
und nicht etwas umgekehrt). Da fehlt noch ein
if (loops_per_jiffy == 0) {
printk("Try an operating system for *fast* machines\n);
abort();
}
[oä]
aber eigentlich nur aus kosmetischen Gründen. Leere Schleife in
numerischen Programmen mögen ein Versehen sein (und somit
'optimierbar') aber in Gerätetreibern sind sie das iA nicht.
>> Aus naheliegenden Gründen begünstigt das Leute, die immer noch
>> am liebsten alles in Assembler schreiben würden und ist mir zB
>> vollkommen egal. Falls der Standard nicht imstande ist, ein
>> brauchbares Verhalten zu definieren, hat das Gremium versagt und
>> nicht der Mensch, der dessen Hinweise notgedrungen ignoriert.
>
> Definiere brauchbares Verhalten fuer die Sprache C.
Im konkreten Fall wäre das: Der Compiler übersetzt
func(56);
zu einem Aufruf der Funktion func(), denn warum ich die an dieser
Stelle aufrufen wollte, kann er nicht wissen und es geht ihn auch
überhaupt nichts an. Falls der Compilerbauer das für einen Fehler
hält, soll der Compiler bitte warnings produzieren. Das wäre sinnvoller
als das hier:
/home/rw/work/sentry/tmp/sentry_conf_file.o2: In function `start_sentry_conf_file':
/home/rw/work/sentry/tmp/sentry_conf_file.o2(.text+0x5a): the use of
`tempnam' is dangerous, better use `mkstemp'
void start_sentry_conf_file(void)
{
char *name;
char const *path;
u8 trials;
int rc;
trials = 0;
path = getenv(CONFIG_PATH);
while (1) {
name = tempnam(path, "sny_");
name || sys_die("start_sentry_conf_file", "tempnam", errno);
rc = open(name, O_RDWR | O_CREAT | O_EXCL, 0600);
if (rc != -1) break;
free(name);
++trials;
if (trials == 0) {
notice("cannot create config file");
exit(1);
}
}
Offenbar bin ich nicht ganz planlos, wie die Autoren der
Bibliotheksfunktion sich das vorgestellt hatten und die Autoren das
Originals waren das sicher auch nicht.
6.5.2.4 Postfix increment and decrement operators
Constraints
1 The operand of the postfix increment or decrement operator shall have
qualified or unqualified real or pointer type and shall be a modifiable
lvalue.
Von was für einem C sprichst Du eigentlich?
[...] Nicht deswegen, damit
> die Leute, die außer ihrem eigenen Geschwätz an nichts glauben,
> solche, die vielleicht etwas lernen möchten, mit maximalem Schwachsinn
> verwirren können.
Bist Du nicht derjenige, der bei Beleidigungen mit einem Anwalt droht?
Jirka
Von dem, von dem Du nicht sprichst und für Menschen und nicht für
Compiler.
> [...] Nicht deswegen, damit
>> die Leute, die außer ihrem eigenen Geschwätz an nichts glauben,
>> solche, die vielleicht etwas lernen möchten, mit maximalem Schwachsinn
>> verwirren können.
>
> Bist Du nicht derjenige, der bei Beleidigungen mit einem Anwalt
> droht?
Falls Du Dich angesprochen fühlst, ist das Pech. Es stand aber nicht
da.
Mal davon abgesehen, daß Du dann hier falsch bist,
++i = i++ soll für Menschen verständlich sein?
Falls es das ist, dann für jeden anders. Und damit
ist es Quatsch.
>>>die Leute, die außer ihrem eigenen Geschwätz an nichts glauben,
>>>solche, die vielleicht etwas lernen möchten, mit maximalem Schwachsinn
>>>verwirren können.
>>
>>Bist Du nicht derjenige, der bei Beleidigungen mit einem Anwalt
>>droht?
>
> Falls Du Dich angesprochen fühlst, ist das Pech. Es stand aber nicht
> da.
Fühle ich mich nicht. Ich frage mich bloß, wie ein mit Beleidigungen
um sich werfender unfreundlicher Kerl wie Du, erwarten kann, mit Be-
leidigungsklagen durchzukommen. Google archiviert.
Jirka
ZB das hier. Im konkreten Fall archiviert es eine durch Dich
begangene, grundsätzlich strafbare Handlung. Über den Unterschied
könntest mal nachdenken.
F'up2p
Rainer Weikusat <weik...@students.uni-mainz.de> wrote:
> Stefan Reuther <sr...@inf.tu-dresden.de> writes:
>> Rainer Weikusat <weik...@students.uni-mainz.de> wrote:
>>> gcc wird das irgendwann tun, nur keine Panik. Ansonsten stellt sich
>>> die Frage, woher der Compiler weiß, was das Programm tun sollte,
>>> inwiefern also ein anderes Programm diese Aufgabe besser erledigen
>>> könnte. Falls ich
>>
>>> a = rand();
>>
>>> schreibe und ein Compiler übersetzt das zu
>>
>>> a = 0;
>>
>>> ist das zunächst mal bloß anders.
>>
>> Das ist auch keine korrekte "Optimierung" von rand().
> In der Tat. Es ist ein Austauschen von Programmteilen nach Maßgabe
> einer undokumentierten Richtlinie auf der Basis von ein paar Annahmen,
> was ich 'eigentlich hätte schreiben wollen', die sich auf nichts
> gründen.
Nein. Wenn ich 'd = 4 * atan(1)' schreibe, dann meine ich
'd = 4 * atan(1)' und nicht 'double d = 3.14159265358979323844'.
Wenn der Compiler der Meinung ist, das in schnelleren, kleineren
Code umzuformen, der dasselbe Ergebnis liefert, find ich das
gut. Und wenn der Compiler das nicht nur bei 'atan', sondern
auch bei 'rand' kann, werd ich mich nicht beklagen.
>>>> Das ist aber ein anderes Problem. Der Standard erlaubt die
>>>> Optimierung sehr wohl,
>>
>>> Was verbessert sie denn im allgemeinen Fall?
>>
>> Es sind immerhin Verbesserungen möglich, wenn ein Programm
>> mehrere Zufallszahlen nacheinander abruft.
> Du hast die Frage nicht beantwortet. Woher weiß der Compiler, welcher
> Algorithmus zur Lösung eines im unbekannten Problems 'optimal' ist und
> wie ist 'optimal' in diesem Zusammenhang definiert?
Üblicherweise 'schnellere Laufzeit' oder 'kürzerer
Maschinencode'. Das Ersetzen einer Funktion durch deren
bekanntes Resultat erfüllt beide dieser Bedingungen.
Oder erwartest du ernsthaft, daß der Compiler
flags = O_CREAT | O_EXCL;
mit einem 'load', einem 'or' und einem 'store' übersetzt?
> Der einzige Effekt, der mir bis
> jetzt praktisch aufgefallen ist, ist der, daß mit irgendwelchen wirren
> und unportablen Tricks dafür sorgt, daß der Optimizer den Code in Ruhe
> läßt, weil er seine primitiven Analysemöglichkeiten übersteigt.
Dann ist üblicherweise der Code falsch. Wer '++i * i++'
schreibt, soll sich nicht beschweren, wenn der Optimierer das
"kaputtmacht".
>>> a = time();
>>> b = rand();
>>> printf("%d\n", time() - a);
>>
>> Und? Egal was der Compiler für 'rand()' einsetzt. Wenn ich den
>> Rechner zwischendurch in den suspend-to-RAM-Modus schicke,
> Gibt es in C nicht.
Genausowenig wir irgendwelche garantierten Qualitäts-
eigenschaften von 'time()' und dem compilierten Code.
Your point?
>> Oder time_t wrappt.
> Kann es nicht. Es ist signed, das Überlaufverhalten also
> undefiniert.
EBEN GENAU DESWEGEN.
>> Abgesehen davon, daß das Programm bei 16-bit ints nicht tut.
> 'implicit int' gibt es nicht mehr.
'%d' hat aber kein 'implicit time_t'.
>>> ergo wäre das Entfernen das Funtionsaufrufes verboten. Ich
>>> habe bewußt 'wäre' geschrieben, weil ein 'Compilerbauer' das
>>> auch nicht zwangsläufig verstehen muß, und, wie zB die
>>> 'Optimierung' von printf("string\n") zu puts("string") durch
>>> gcc zeigt, auch wahrscheinlich nicht tut.
>>
>> printf->puts ist für eine Hosted-Umgebung eine zulässige
>> Optimierung, auch wenn du tausendmal das Gegenteil behauptest.
>> Bitte Kapitel und Vers zitieren. Ich
> Das hatte ich bereits getan. Das hier ist strictly conforming:
[...]
> t0 = clock();
>
> sqrt(4);
[...]
> t0 = clock() - t0;
> return t0;
> Den 'Unterschied' kann ich nur dann nicht festellen, falls clock() bei
> einer konkreten Implementierung immer -1 liefert.
Wie stellst du einen 'Unterschied' zwischen "optimiert" und
"nicht optimiert" fest, ohne das Programm zweimal mit
unterschiedlichen Optimizer-Flags zu übersetzen? 'gcc -O0' ist
eine andere C-Implementierung als 'gcc -O2'. Face it.
Stefan
>Bodo Thiesen schrieb:
>
>> Rainer Weikusat <weik...@students.uni-mainz.de> wrote:
>>
>>> Dito für Herrn Reibenstein.
>
> Um was geht's eigentlich? Ich sehe die Nachrichten von Rainer nicht,
> also seid so lieb und klärt mich auf.
Ich weiß es ja selber nicht ...
>> Was hat /er/ denn jetzt verbrochen?
>
> Na, da bin ich aber gespannt :-)
Ich auch.
Schon klar. Mit der Frage des OP hat das allerdings nichts zu tun.
Genau genommen halte ich sie im Rahmen des Standards für nicht
beantwortbar.
<20030820115221....@brachttal.net>
# Oder muss ich das wirklich selbst optimieren?
Standard ist Standard.
Unabhängig davon gibt es Aussagen wie
a) Funktioniert überall, bis auf ein paar kranke Ausnahmen.
a) Funktioniert nirgends, bis auf ein paar kranke Ausnahmen.
Es gibt bestimmt einen real existierenden Compiler, der aus
# for (i=0;i<100000;i++)
# {
# test = sqrt (3) * i;
# }
den Funktionsaufruf nicht optimiert.
Umgekehrt bin ich mir aber nicht sicher, ob es auch real existierende
Compiler gibt, die das für dieses Beispiel oder gar einen verallge-
meinerten Fall machen.
Dass der Standard die Optimierung nicht verbietet und die Implemen-
tierung durch die explizite Nennung reservierter Namen sogar
begünstigt, heisst noche lange nicht, dass diese Optimierung auch
zumindest von einem real-existierenden Compiler durchgeführt wird,
und schon gar nicht, dass die Mehrzahl der üblichen Compiler das
so machen.
Ich denke nicht, dass ich hier mit dem Nitpicking angefangen habe.
Gemeint habe ich bloss, dass in
<igmvhb...@news.musoftware.de>
# Die Namen der Standard Funktionen sind reserviert, koennen also
# nicht fuer eigene Funktionen verwendet werden.
das "koennen" durch ein "duerfen" ersetzt werden sollte.
Alles andere geht gegen den Geist von C.
--
Google ist Gott. Opfere ihr deine Zeit und werde erleuchtet.
> Ergo ist die Ausage 'X wird durch den C-Standard verboten' dann
> falsch, wenn es um syntaktisch und grammatikalisch korrekte
> Formulierungen geht, deren Semantik nicht standardisiert ist.
> ++i = i++
> ist vollkommen 'legales' C, bloß hängt es von der Implementierung ab,
> in welcher Reihenfolge die Seiteneffekte wirksam werden.
Es hängt auch von der Implementierung ab, ob das überhaupt
übersetzt wird. Merke: 'undefined' kann alles bedeuten, inkl.
Compilerfehler.
Der Standard garantiert *dem Compiler*, daß kein Objekt zwischen
zwei Sequenzpunkten mehrfach modifiziert wird. Ich kenne keine
Details von ia64, aber dort ist es möglich, mehrere
Instruktionen gleichzeitig auszuführen. Generiert der Compiler
nun zwei 'gleichzeitige' Stores auf dieselbe Adresse, ist ein
bus-error nicht gerade unwahrscheinlich.
[...]
> ein akzeptables Compilerverhalten wäre und das wird deswegen nicht
> explizit verboten, weil jemand, der wenigstens eine minimale
> Vorstellung davon hat, wie ein Computerprogramm arbeitet, sich darüber
> im Klaren ist, das man diesen Sonderfall gezielt abfangen und
> absichtlich anders behandeln müßte, als
> ++i;
> i = ++i;
> und zwar auschließlich deswegen, weil man jemanden gezielt in den
> Arsch treten möchte.
Du hast noch nie einen Compiler geschrieben, sag das doch
gleich.
Code wie 'a[i++] = ++i' ist deswegen undefiniert, damit der
Compiler eben *nicht* erkennen muß, daß sowohl der Array-Index
als auch der Wert rechts vom '=' die gleiche Variable verwenden.
Je nach CPU, Optimierungsflags und Wetterlage darf der Compiler
also entweder die rechte oder die linke Seite zuerst bewerten.
Oder beide gleichzeitig. Du möchtest entweder strikte
links-nach-rechts oder rechts-nach-links Auswertung, und *das*
ist Unsinn. Das wäre Stand der Compilertechnik von 1960.
>> Warum hast Du denn nicht dafuer gesorgt dass der Standard so
>> ausssieht wie Du ihn gerne haettest? Ist AFAIK nicht ganz
>> unmoeglich.
> Der C-Standard selber ist nicht annähernd so wahnsinnig, wie er hier
> gerne von Leuten, denen scheinbar das Hintergrundwissen fehlt, um ihn
> zu verstehen, gerne interpretiert wird.
Ich sehe hier eigentlich nur einen, der ständig 'C ist Mist weil
<codefragment>' postet.
>>> Das funktioniert ähnlich wie xdr: Wir nehmen das native Format
>>> unseres Systems [...]
>>
>> Oha!
>>
>> Du hast also die Loesung fuer das Problem dass man fuer ein
>> "over-the-wire" Protokoll irgendwelche Datendarstellungen
>> festlegen muss? Bwahahaha!
> Nein, ich 'habe' die nicht, aber OSF DCE-RPC hatte mal eine, nämlich
> das Datenformat ebenfalls zu kommunizieren, damit Konversionen nur
> dann durchgeführt werden müssen, wenn sie tatsächlich notwendig sind:
> For instance, consider two VAX-11 machines using a protocol
> that relies on XDR encoding. Since the VAX is little endian
> ([...]), the sender would have to convert each integer to
> big-endian form (mandated by XDR), and the receiver would have
> to convert it back to little-endian form.
Wo ist jetzt das Problem? Diese Konvertierung kostet auf x86
einen halben Takt. Wenn Endian-Konvertierung für das
Marktsegment der VAX-Benutzer zum Flaschenhals wird, sollen sie
in ihre CPUs halt eine 'bswap'-Instruktion einbauen.
> This wasteful
> exercise could be prevented if the representation some means
> of communicatin the machine characteristics, so that
> conversions where only required for unlikely machines.
> [UNIX Internal, p. 299/300]
In anderen Worten, wir machen aus
bswap(&value);
ein
if (sender_has_other_endian)
bswap(&value);
Der Test kostet auch nur 5x soviel wie der eigentliche swap. Super.
Was hat das eigentlich mit dem Thema dieser GABELN zu tun?
> In short garantiert das, das Sun-Rechner (traditionell big-endian)
> immer einen höheren NFS-Durchsatz erzielen werden, als andere, was den
> Erfindern dieser Repräsentation nicht ganz unlieb gewesen sein
> dürfte.
So what? Offenbar hat sich NFS durchgesetzt, einfach weil es da
war und funktionierte. Es gab auch von DEC ein Netzwerk. Das
konnte man sogar verwenden. Aber offenbar hat NFS überlebt und
das DEC-Teil (Pathworks?) nicht.
Ach ja, und die Endian-Konvertierung macht natürlich bei
Netzwerk-Kommunikation den Löwenanteil am Zeitbedarf aus.
>> Welche Darstellung waere denn politisch korrekt? NUXI? XUNI? Alles
>> in ASCII? Irgendwas was keine existierende Hardware tut und wir
>> verbieten dass zukuenftige Hardware das benutzt?
> Um aufs topic zurückzukommen: C-Stringfunktionen heißen normalerweise
> strirgendwas. Falls ich mit drei Systemen zu tun habe, von denen zwei
> eine Funktion namens 'strlcpy' bieten, mag ich nicht einsehen, warum
> ich das im Code so behandeln sollte:
[snip]
Das verbietet dir keiner. Du mußt halt nur in dieser Gruppe
damit leben, daß jemand dich darauf hinweist, daß es nicht
funktionieren muß. Genauso wie man in anderen Newsgruppen
OE-Benutzer darauf hinweist, daß undeklarierte Umlaute
funktionieren können, aber nicht müssen.
[schnipp]
> aber eigentlich nur aus kosmetischen Gründen. Leere Schleife in
> numerischen Programmen mögen ein Versehen sein (und somit
> 'optimierbar') aber in Gerätetreibern sind sie das iA nicht.
Dann sag dem Compiler, daß du einen Gerätetreiber compilierst.
Fertig. Da mehr Leute ein Anwendungsprogramm schreiben als einen
Gerätetreiber, darf der Compiler durchaus erstmal von ersterem
ausgehen.
>>> Aus naheliegenden Gründen begünstigt das Leute, die immer noch
>>> am liebsten alles in Assembler schreiben würden und ist mir zB
>>> vollkommen egal. Falls der Standard nicht imstande ist, ein
>>> brauchbares Verhalten zu definieren, hat das Gremium versagt und
>>> nicht der Mensch, der dessen Hinweise notgedrungen ignoriert.
>>
>> Definiere brauchbares Verhalten fuer die Sprache C.
> Im konkreten Fall wäre das: Der Compiler übersetzt
> func(56);
> zu einem Aufruf der Funktion func(), denn warum ich die an dieser
> Stelle aufrufen wollte, kann er nicht wissen und es geht ihn auch
> überhaupt nichts an. Falls der Compilerbauer das für einen Fehler
> hält, soll der Compiler bitte warnings produzieren. Das wäre sinnvoller
> als das hier:
> /home/rw/work/sentry/tmp/sentry_conf_file.o2: In function `start_sentry_conf_file':
> /home/rw/work/sentry/tmp/sentry_conf_file.o2(.text+0x5a): the use of
> `tempnam' is dangerous, better use `mkstemp'
Das *ist* eine Warnung. Und die kommt im übrigen vom Linker,
weil der Autor der von dir verwendeten libc der Meinung war,
dich da mit einer Warnung zu beglücken. Find ich auch nicht
unbedingt toll. Genauso wie 'warning: printf adds 6k bloat to
your code'.
> Offenbar bin ich nicht ganz planlos, wie die Autoren der
> Bibliotheksfunktion sich das vorgestellt hatten und die Autoren das
> Originals waren das sicher auch nicht.
Wenn du glaubst, unfehlbar zu sein, stell die Warnungen halt ab.
Daß das bei GNU ld nicht so einfach zu sein scheint, ist in der
Tat schwach. Aber es gibt ja
$ perl -pi -e 's/\.gnu\.warning\./.gnu.ignore!./' libc.a
Stefan
>Es gibt bestimmt einen real existierenden Compiler, der aus
>
># for (i=0;i<100000;i++)
># {
># test = sqrt (3) * i;
># }
>
>den Funktionsaufruf nicht optimiert.
Weder gcc2.8.1 noch gcc2.95.3 (x86) tun es. Gut, immerhin schaffen sie
es, das fsqrt des Coprozessors direkt zu benutzen, statt _sqrt
aufzurufen.
Vinzent.
> Mathias Grimmberger <mg...@zaphod.sax.de> writes:
>> Rainer Weikusat <weik...@students.uni-mainz.de> writes:
>
> ++i = i++
Das Problem mit solchen Dingern ist, daß es Leute (Anfänger) gibt, die
glauben, in solchen Ausdrücken ein definiertes Verhalten zu sehen, und
sich dann wundern, warum auf System X plötzlich etwas ganz anders
passiert. Natürlich passiert da /irgendetwas/, aber über das /was/
schweigt sich der Standard aus, und wenn man ein strictly Conforming
Programm schreiben will, bleibt einem kaum was anderes übrig, als
nur sowas zu tun, wozu der Standard auch vollständige Garantien macht.
>ist vollkommen 'legales' C,
Ne. Es ist gerade noch Syntaktisch einwandfrei.
Ein Haus läuft gestern um den sich fürchtenden Vorhang heiß.
So, ist das jetzt einwandfreies Deutsch oder nicht?
> bloß hängt es von der Implementierung ab, in welcher Reihenfolge die
> Seiteneffekte wirksam werden.
Ach? Dürfte es nicht auch Implementierungen geben, die hier auch was
ganz anderes machen? Eventuell wird ja auch der Wert i & (i+1)
geschrieben (und das ist jetzt nicht so wie mit dem gelben Warzenschwein,
sondern eine logische Möglichkeit dessen, was passieren könnte).
> Es bedeutet nicht, daß eine Übersetzung,
> die nach C rückübersetzt, so aussähe:
>
> i = sqrt(3.14) - 3177; /* whatever */
Aber vielleicht nach i &= i + 1;
>ein akzeptables Compilerverhalten wäre und das wird deswegen nicht
>explizit verboten, weil jemand, der wenigstens eine minimale
>Vorstellung davon hat, wie ein Computerprogramm arbeitet, sich darüber
>im Klaren ist, das man diesen Sonderfall gezielt abfangen und
>absichtlich anders behandeln müßte, als
>
> ++i;
> i = ++i;
>
>und zwar auschließlich deswegen, weil man jemanden gezielt in den
>Arsch treten möchte. Die Leute, die solchen Unsinn propagieren, sollen
>bitte Compiler schreiben, die sich so verhalten, und dann man
>abwarten, welche Marktdurchdringung die unter Berücksichtigung von
>'quality of implementation' erreichen. Mutmaßlich keine, was
>ausdrücklich konform zur Intention des C-Standards ist.
Schreib weiter Code, der seine Semantik ändert, nur weil man eine
Optimierung ein oder ausschaltet. Aber lass doch diese Newsgroup damit in
Ruhe, bitte.
>Falls reale
>Implementierungen von C hier nicht erwünscht sind, fällt es mir leider
>schwer, zu verstehen, warum das für fiktionale Implementierung nicht
>auch gilt.
Wenn Du den Beweggrund für solche Aussagen nicht verstehst, bist Du hier
falsch. Ganz einfach.
Dann hast Du ein deutliches Problem mit logischem Denken. Wenn etwas
undefiniert gelassen wird, bestehen keine Einschränkungen. Insbesondere
keine Einschränkung, die etwas für oder gegen gelbe Warzenschweine
aussagt.
...
# Ergo ist die Ausage 'X wird durch den C-Standard verboten' dann
# falsch, wenn es um syntaktisch und grammatikalisch korrekte
# Formulierungen geht, deren Semantik nicht standardisiert ist.
#
# ++i = i++
#
# ist vollkommen 'legales' C,
Es ist maximal 'weikusat-legal', aber nicht 'ISO-C legal' denn, und das
jetzt zum mitmeißeln, auch die Semantik ist Teil dessen, was ISO C
standardisiert hat. Die Trennung zwischen Syntax und Semantik gibt es
bei Betrachtungen über ISO-C Legalität nicht. Punkt.
Regards,
Jens
--
Jens Schweikhardt http://www.schweikhardt.net/
SIGSIG -- signature too long (core dumped)
... dann wird es *undefiniert* gelassen, was etwas anderes ist, als
*beliebig definiert*.
> ...
> # Ergo ist die Ausage 'X wird durch den C-Standard verboten' dann
> # falsch, wenn es um syntaktisch und grammatikalisch korrekte
> # Formulierungen geht, deren Semantik nicht standardisiert ist.
> #
> # ++i = i++
> #
> # ist vollkommen 'legales' C,
>
> Es ist maximal 'weikusat-legal', aber nicht 'ISO-C legal' denn, und das
> jetzt zum mitmeißeln, auch die Semantik ist Teil dessen, was ISO C
> standardisiert hat. Die Trennung zwischen Syntax und Semantik gibt es
> bei Betrachtungen über ISO-C Legalität nicht. Punkt.
Das ist eine Meinung und keine Tatsache. Eine Tatsache ist vielmehr,
das Compiler Programm anhand statischer Regeln übersetzen (dito für
Interpreter) und dazu gehört zB eine Grammatik, nach deren Maßgabe man
beurteilen, was eine grammatisch wohlgeformte Formulierung ist und was
nicht. Zb ist 'Das Bankgebäude wirbelte auf dem Absatz herum und zog
seinen Revolver' ein korrekter deutscher Satz ohne Sinn. Analog gilt
das für a[++i] = i++ in C. Das wäre eine übliche linguistische
Betrachtungsweise für Sprachen.
Die Gruppe behandelt standardkonformes C, d.h. Programme, die "strictly
conforming" sind. Das "koennen" heisst also ausgeschrieben "koennen bei
standardkonformen Programmen". Ich spare mir diese explizite Form bloss immer,
weil das sonst so viel zu tippen ist. Und bei
Die Namen der Standard Funktionen sind reserviert, koennen also bei
standardkonformen Programmen nicht fuer eigene Funktionen verwendet
werden.
darf das "koennen" keinesfalls durch ein "duerfen" ersetzt werden. Ein
standardkonformes Programm waere naemlich sonst nicht mehr standardkonform.
> Alles andere geht gegen den Geist von C.
Wo ist der Geist von C definiert? Wenn Du mit "weichen" Kriterien wie dem
"Geist von C" anfaengst, dann komme ich demnaechst mit meinem Horoskop:-)
Gruss
Uz
--
Ullrich von Bassewitz u...@remove-to-reply.musoftware.de
2:10pm up 197 days, 20:56, 69 users, load average: 0.20, 0.21, 0.17
Ja. Und undefiniert heißt undefiniert heißt undefiniert. Es heißt nicht:
"irgendwas, aber keine gelben Warzenschweine". Denn das wäre schon eine
Einschränkung. Im Standard steht sogar drin "for which this
International Standard makes no reuqirements." Damit es selbst ein Kind
kapiert: Wenn ich sage, "male was Du willst", und es malt ein gelbes
Warzenschwein, dann hat es nicht gegen meine Vorgaben verstoßen.
#> ...
#> # Ergo ist die Ausage 'X wird durch den C-Standard verboten' dann
#> # falsch, wenn es um syntaktisch und grammatikalisch korrekte
#> # Formulierungen geht, deren Semantik nicht standardisiert ist.
#> #
#> # ++i = i++
#> #
#> # ist vollkommen 'legales' C,
#>
#> Es ist maximal 'weikusat-legal', aber nicht 'ISO-C legal' denn, und das
#> jetzt zum mitmeißeln, auch die Semantik ist Teil dessen, was ISO C
#> standardisiert hat. Die Trennung zwischen Syntax und Semantik gibt es
#> bei Betrachtungen über ISO-C Legalität nicht. Punkt.
#
# Das ist eine Meinung und keine Tatsache.
Eine, über die hier und in comp.std.c große Übereinkunft herrscht. Ich
kenne nur eine einzige Person, die es nicht kapiert hat und neben
Aufstampfen mit dem Fuß nichts zu bieten hat.
# Eine Tatsache ist vielmehr,
# das Compiler Programm anhand statischer Regeln übersetzen (dito für
# Interpreter) und dazu gehört zB eine Grammatik, nach deren Maßgabe man
# beurteilen, was eine grammatisch wohlgeformte Formulierung ist und was
# nicht. Zb ist 'Das Bankgebäude wirbelte auf dem Absatz herum und zog
# seinen Revolver' ein korrekter deutscher Satz ohne Sinn. Analog gilt
# das für a[++i] = i++ in C. Das wäre eine übliche linguistische
# Betrachtungsweise für Sprachen.
Wie Du das betrachtest und nennst ist mir egal. In meiner, des
Standards, und dem Rest der Welt \ {Weikusat} Ansicht ist die Klasse der
Dateien mit der Eigenschaft "Ist eine Sequenz aus C preprocessing token"
für nichts anderes gut, denn als Eingabe für Translation phase 1.
Unwesentlich später ist "a[++i] = i++" undefiniert und der Compiler
seiner Pflichten ledig. Wenn Du das anders siehst, dann Kapitel und
Vers, was er daraus machen muß. Sonst muß ich davon ausgehen, daß Du nur
Wunschdenken äußerst.
Ach, das ist also implementation-defined? Kapitel und Vers, bitte. Ich
halte dagegen, daß dies undefined ist, und Kapitel und Vers kann ich Dir
gerne zitieren, falls Du sie nicht findest.
Jirka Klaue <jkl...@ee.tu-berlin.de> wrote:
> Rainer Weikusat wrote:
> ...
>> Ergo ist die Ausage 'X wird durch den C-Standard verboten' dann
>> falsch, wenn es um syntaktisch und grammatikalisch korrekte
>> Formulierungen geht, deren Semantik nicht standardisiert ist.
>>
>> ++i = i++
>>
>> ist vollkommen 'legales' C, bloß hängt es von der Implementierung ab,
>> in welcher Reihenfolge die Seiteneffekte wirksam werden.
Wenn das das erste ++ weggelassen worden waere, waere es moeglicherweise
noch korrekte C-Syntax, aber dadurch noch kein korrektes C. So etwas (und
damit meine ich jetzt die Variante "i=i++") ist im Standard aus gutem Grund
als "undefined" bezeichnet (und nicht etwa nur "implementation defined"),
und damit selbstverstaendlich kein korrektes C im Sinne des Standards mehr.
> 6.5.2.4 Postfix increment and decrement operators
> Constraints
> 1 The operand of the postfix increment or decrement operator shall have
> qualified or unqualified real or pointer type and shall be a modifiable
> lvalue.
> Von was für einem C sprichst Du eigentlich?
Die von Rainer gepostete Variante hielt ich noch nicht einmal fuer noetig
unveraendert zu kommentieren, da schon die "entschaerfte" Variante ohne
das increment auf der linken Seite bereits "undefined" ist ...
Tschuess,
Juergen Ilse (jue...@usenet-verwaltung.de)
--
[ Urs Traenkner in dcsf daueber das Computer komplexe Geraete sind ]
Und dass Windows so tut, als ob es sich bei einem PC um ein Tamagotchi
handeln wuerde (leg mich schlafen: bluescreen, knuddel mich: reboot,
gib mir essen: weiter, ok, abbrechen usw.), aendert nichts an dieser Tatsache.
Stefan Reuther <sr...@inf.tu-dresden.de> wrote:
> Rainer Weikusat <weik...@students.uni-mainz.de> wrote:
[...]
>> ++i = i++
>> ist vollkommen 'legales' C, bloß hängt es von der Implementierung ab,
>> in welcher Reihenfolge die Seiteneffekte wirksam werden.
Falsch, das ist nicht nur "undefined" sondern noch nicht einmal mehr C.
> [...]
>> ein akzeptables Compilerverhalten wäre und das wird deswegen nicht
>> explizit verboten, weil jemand, der wenigstens eine minimale
>> Vorstellung davon hat, wie ein Computerprogramm arbeitet, sich darüber
>> im Klaren ist, das man diesen Sonderfall gezielt abfangen und
>> absichtlich anders behandeln müßte, als
>> ++i;
>> i = ++i;
>> und zwar auschließlich deswegen, weil man jemanden gezielt in den
>> Arsch treten möchte.
Nun ist wenigstens aus "ist kein C" schon "in laut standard undefined"
geworden, das ist aber ehrlich gesagt nur eine relativ minimale Verbesserung.
"i" wird hier (in der unteren Zeile) mehrfach geaendert, ohne dann ein
Sequenzpunkt dazwischen liegen wuerde. Du darfst selbst im Standard nachlesen,
warum das "undefined behaviour" bedeutet.
>> Der C-Standard selber ist nicht annähernd so wahnsinnig, wie er hier
>> gerne von Leuten, denen scheinbar das Hintergrundwissen fehlt, um ihn
>> zu verstehen, gerne interpretiert wird.
Keines der beiden von dir zitierten Codefragmente ist vom Standard gedeckt
(auch, wenn du beide Konstrukte gern als "vollkommen legales C" ansehen
wuerdest). Wovon redest du also?
>Ergo ist die Ausage 'X wird durch den C-Standard verboten' dann
>falsch, wenn es um syntaktisch und grammatikalisch korrekte
>Formulierungen geht, deren Semantik nicht standardisiert ist.
> ++i = i++
>ist vollkommen 'legales' C, bloß hängt es von der Implementierung ab,
>in welcher Reihenfolge die Seiteneffekte wirksam werden.
Du bist darauf hingewiesen worden, dass das, was "legales C" ist, bei
weitem nicht mit einem "syntaktisch und grammatikalisch korrekt" hin-
reichend umschrieben ist.
Ich habe mit solchen Behauptungen ein weiteres Problem: Erklaere mir
doch mal, was in C "Syntax" von "Semantik" unterscheidet. Falls das auf
(die kanonische Erklaerung) "Syntax ist das, was mit formalen Regeln/
Produktionen/Ableitungen ueberprueft wird." hinaus laeuft, und Cs
"Syntax" dann die Eisenbahndiagramme im Anhang von K&R, resp. das, was
in den Standards jeweils unter der Ueberschrift "Syntax" zu finden ist,
sind, dann verkaufe dem gespanntem Publikum doch bitte z.B. (ein
notorisches)
int; main() {}
als "legales C", weil's syntaktisch korrekt ist. Ach so, da ist kein
Tippfehler 'drin.
Du sitzt uebrigens wieder dem Anfaengerfehler auf (oder versuchst ihn
bewusst zu kultivieren), UB mit den Interna einer Implementation
"erklaeren" zu wollen. Dieses `++i = i++' ist nicht "nur" undefiniert,
weil's "bloss" von der "Reihenfolge die Seiteneffekte" abhaengen
wuerde.
Was Du wenig spaeter selbst belegst und illustrierst:
>[...] weil jemand, der wenigstens eine minimale
>Vorstellung davon hat, wie ein Computerprogramm arbeitet, sich darüber
>im Klaren ist, das man diesen Sonderfall gezielt abfangen und
>absichtlich anders behandeln müßte, als ...
> ++i;
> i = ++i;
ist naemlich *ganz* *genauso* UB und Du hast damit ueberhaupt nichts
"abgefangen". 6.5p2. Trotz, nein wegen! Deiner "minimalen Vorstellungen
davon, wie ein Computerprogramm arbeitet".
> ... und zwar auschließlich deswegen, weil man jemanden gezielt in den
>Arsch treten möchte.
[X] Send Pix - Du hast applizierst diesen Tritt bei Dir selbst.
b.
[...]
> ++i = i++
>
> ist vollkommen 'legales' C, [...]
Ich bin jetzt doch etwas verwundert über daß, was hierzu schon geschrieben
wurde. "Implementationsdefiniert", "undefiniert", "gerade noch
syntaktisch einwandfrei". Nein, dies ist alles Andere als legales C!
Der Ausdruck ++i liefert einen Wert, kann also nicht der linke Operand des
Zuweisungsoperators sein. Ich denke, entsprechende Zitate aus dem
Standard kann ich mir hier sparen.
cc
[ undefined behaviour ]
> #> Dann hast Du ein deutliches Problem mit logischem Denken. Wenn etwas
> #> undefiniert gelassen wird,
> #
> # ... dann wird es *undefiniert* gelassen, was etwas anderes ist, als
> # *beliebig definiert*.
>
> Ja. Und undefiniert heißt undefiniert heißt undefiniert.
Du wiederholst mich. Wofür? 'Undefiniert' heißt in C exakt 'der
Standard macht keine Aussage dazu', nicht
$willkürlicher_blödsinn_der_mir_gerade_in_den_sinn_kam.
Für alle praktischen Zwecke bedeutet 'undefined' 'implementation
defined' und die konkrete Reaktion einer Implementierung läßt sich
auch ermitteln. Als Beispiel verweise ich auf das 'Endianess bei
Bitfeldern'-Posting von vor einer Weile. Der C-Standard gestattet es
sogar ausdrücklich, das Programme solche Effekte ausnutzen ('A
conforming programm is something accepted by a conforming
implementation'). Vgl Lisp: Wenn dort etwas als 'is an error'
definiert ist, muß eine Implementierung das zwar nicht erkennen, aber
sie darf kein sinnvolles dokumentiertes Verhalten dafür
haben. C-Implementierungen dürfen das auch für 'undefined behaviour'
denn ist undefined (undefined, undefined) und nicht wrong (wrong,
wrong), falls das in Kleinkindersprache evtl besser ankommt. Es wird
sogar ausdrücklich zwischen 'errnous usage' und 'undefined behaviour'
unterschieden: Ersteres ist eine Teilmenge von letzterem.
> # Eine Tatsache ist vielmehr,
> # das Compiler Programm anhand statischer Regeln übersetzen (dito für
> # Interpreter) und dazu gehört zB eine Grammatik, nach deren Maßgabe man
> # beurteilen, was eine grammatisch wohlgeformte Formulierung ist und was
> # nicht. Zb ist 'Das Bankgebäude wirbelte auf dem Absatz herum und zog
> # seinen Revolver' ein korrekter deutscher Satz ohne Sinn. Analog gilt
> # das für a[++i] = i++ in C. Das wäre eine übliche linguistische
> # Betrachtungsweise für Sprachen.
>
> Wie Du das betrachtest und nennst ist mir egal.
Das nenne allerdings nicht ich so, sondern ein nennenswerter Korpus an
sprachwissenschaftlicher Fachliteratur und C ist genauso eine von
Menschen geschaffene Sprache wie Deutsch oder Esperanto. Solange Du
nichts besseres als 'Mir doch egal' zu bieten hast, mußt Du Dir da den
Vorwurf der Unsachlichkeit, des 'Füße aufstampfens', um in Deiner
Diktion zu bleiben, gefallen lassen.
> Rainer Weikusat wrote:
>
>> ++i = i++
>>
>> ist vollkommen 'legales' C
Da ist mein Compiler aber ganz anderer Meinung (und ich auch):
Error d:\ctest\ctest.c: 8 the left hand side of the assignment can't
be assigned to
Es hätte mich auch sehr gewundert, wenn ++i plötzlich ein lvalue wäre.
> 6.5.2.4 Postfix increment and decrement operators
Wohl eher 6.5.16 "Assignment operators", Absatz 2:
An assignment operator shall have a modifiable lvalue as its left
operand.
Gruß. Claus
> Merke: 'undefined' kann alles bedeuten, inkl.
> Compilerfehler.
'undefined' bedeutet allerdings etwas, nämlich (haha) 'undefined'.
Merke: Das heißt auch, 'das Konstrukt wird zu ++(i = (j = i, ++j))'
übersetzt. BZW es heißt das auch nicht.
> Der Standard garantiert *dem Compiler*, daß kein Objekt zwischen
> zwei Sequenzpunkten mehrfach modifiziert wird.
Der Standard sagt, das sowas durch ihn nicht definiert
wird. Wörtlich.
>> ein akzeptables Compilerverhalten wäre und das wird deswegen nicht
>> explizit verboten, weil jemand, der wenigstens eine minimale
>> Vorstellung davon hat, wie ein Computerprogramm arbeitet, sich darüber
>> im Klaren ist, das man diesen Sonderfall gezielt abfangen und
>> absichtlich anders behandeln müßte, als
>
>> ++i;
>> i = ++i;
>
>> und zwar auschließlich deswegen, weil man jemanden gezielt in den
>> Arsch treten möchte.
>
> Du hast noch nie einen Compiler geschrieben, sag das doch
> gleich.
C-Bezug?
>
> Code wie 'a[i++] = ++i' ist deswegen undefiniert, damit der
> Compiler eben *nicht* erkennen muß, daß sowohl der Array-Index
> als auch der Wert rechts vom '=' die gleiche Variable verwenden.
Darf ich Dich zitieren? BTW, die Annahme ist falsch.
>> Der C-Standard selber ist nicht annähernd so wahnsinnig, wie er hier
>> gerne von Leuten, denen scheinbar das Hintergrundwissen fehlt, um ihn
>> zu verstehen, gerne interpretiert wird.
>
> Ich sehe hier eigentlich nur einen, der ständig 'C ist Mist weil
> <codefragment>' postet.
Du halluzinierst.
>> Nein, ich 'habe' die nicht, aber OSF DCE-RPC hatte mal eine, nämlich
>> das Datenformat ebenfalls zu kommunizieren, damit Konversionen nur
>> dann durchgeführt werden müssen, wenn sie tatsächlich notwendig sind:
>
>> For instance, consider two VAX-11 machines using a protocol
>> that relies on XDR encoding. Since the VAX is little endian
>> ([...]), the sender would have to convert each integer to
>> big-endian form (mandated by XDR), and the receiver would have
>> to convert it back to little-endian form.
>
> Wo ist jetzt das Problem? Diese Konvertierung kostet auf x86
> einen halben Takt.
Das ist technisch unmöglich. Es ist hier außerdem OT, einschließlich
Deiner Verständnisprobleme damit.
>> Um aufs topic zurückzukommen: C-Stringfunktionen heißen normalerweise
>> strirgendwas. Falls ich mit drei Systemen zu tun habe, von denen zwei
>> eine Funktion namens 'strlcpy' bieten, mag ich nicht einsehen, warum
>> ich das im Code so behandeln sollte:
> [snip]
>
> Das verbietet dir keiner. Du mußt halt nur in dieser Gruppe
> damit leben, daß jemand dich darauf hinweist, daß es nicht
> funktionieren muß.
Das ist nicht 'falsch', sondern bloß nicht
auf alle denkbaren C-Implementierungen portabel (und vermutlich auch
auf ein paar reale nicht).
Welchen Teil davon möchtest Du detailliert erklärt haben? (ich tue mal
so, als ob Du an einem Thema interessiert wärest, was Du natürlich
nicht bist).
>> zu einem Aufruf der Funktion func(), denn warum ich die an dieser
>> Stelle aufrufen wollte, kann er nicht wissen und es geht ihn auch
>> überhaupt nichts an. Falls der Compilerbauer das für einen Fehler
>> hält, soll der Compiler bitte warnings produzieren. Das wäre sinnvoller
>> als das hier:
>
>> /home/rw/work/sentry/tmp/sentry_conf_file.o2: In function `start_sentry_conf_file':
>> /home/rw/work/sentry/tmp/sentry_conf_file.o2(.text+0x5a): the use of
>> `tempnam' is dangerous, better use `mkstemp'
>
> Das *ist* eine Warnung.
Ach nein.
>> Offenbar bin ich nicht ganz planlos, wie die Autoren der
>> Bibliotheksfunktion sich das vorgestellt hatten und die Autoren das
>> Originals waren das sicher auch nicht.
>
> Wenn du glaubst, unfehlbar zu sein,
Wenn Du Dich für ein fünfundzwanzig Zenter wiegende Vorstadthure
hälst, solltest Du nicht über dünne Brücken gehen, falls Du Höhenangst
hast. Wenn Du das nicht tust, darfst Du diesen Satz als
zusammenhanglos ignorieren. Klingelts da irgendwo?
Uhh, da hast Du aber ein schlechtes Beispiel ausgesucht.
Zitate aus ISO/IEC 9899:1999
4.1 In this International Standard, shall is to be interpreted as a
requirement on an implementation or on a program; conversely, shall not
is to be interpreted as a prohibition.
(folgendes ist ein constraint fuer Zuweisungsoperatoren)
6.5.16.2 An assignment operator shall have a modifiable lvalue as its
left operand.
Ist ++i ein "modifiable lvalue"? Ich glaub nicht, also ist das nicht
(semantisch) legales C.
[snip]
Hmm, hmm. Du meinst ernsthaft dass Sun einen echten Vorteil hat weil
ein paar Header-Felder umgewandelt werden muessen? Glaub ich nicht.
Und Deine Idee ist dann dass man im Protokoll eine (sicher nicht ganz
triviale) Moeglichkeit implementiert um das Datenformat auszuhandeln?
Inklusive so netter (und nicht ganz unwahrscheinlicher) Fallen wie
optional zu unterstuetzende Formate?
Und das soll besser sein als ein festes Format?
Wo denn?
War Deine Beschwerde nicht genau dass Du "unnoetigen" Aufwand betreiben
musst weil es einigen Herstellern gelang ihr natives Format als Standard
durchzusetzen? Was uebrigens Unfug ist weil Du in jedem Fall mehr
Aufwand haben koenntest - auch wenn Sun das Intel-Format spezifiziert
haette und Du halt Sun-Hardware benutzt.
> <nitpick>
> big endian
> </>
Kann ich mir nie merken...
> > MPEG auch?
>
> MPEG in jedem Fall. »Leider war unser erste Entwurf vollkommener
> Bullshit, deswegen definieren wir den alten Header als konstant und
> die 'echten Daten' stehen im Erweiterungsheader dahinter«, aka »This
> bit is here for historical reasons and shall have the value one«.
Ein Standard ist nicht deshalb nuetzlich weil er die bestmoegliche
Loesung fuer ein Problem definiert sondern weil er Interoperabilitaet
sichert (bis zu einem gewissen Grad jedenfalls).
Wirklich zu schlechte Standards werden ignoriert.
> Das ist übrigens dasselbe Verfahren: Wir definieren ein
> schwachsinniges Datenformat und stellen eine grottige
> Referenzimplementierung kostenlos zur Verfügung, wodurch wir uns ein
> ewiges Einkommen via royalties von den Leuten, die unseren Abfall in
> einen funktionsfähigen Zustand überführen sollen, sichern.
Da ist ein voellig anderes Problem. Die Leute, die heute immerzu von
Wissensgesellschaft und Intellectual Property faseln, werden hoffentlich
als erste an die Wand gestellt wenn es soweit ist.
> Um aufs topic zurückzukommen: C-Stringfunktionen heißen normalerweise
> strirgendwas. Falls ich mit drei Systemen zu tun habe, von denen zwei
> eine Funktion namens 'strlcpy' bieten, mag ich nicht einsehen, warum
> ich das im Code so behandeln sollte:
>
> #if !defined(linux)
> # define bounded_buffer_string_copy strlcpy
> #else
> char *bounded_buffer_string_copy(char *d, char const *s, size_t l)
> {
> .
> .
> .
> }
> #endif
>
> falls ich an 'maximaler Portabilität', aka 'läuft auf jedem Toaster'
> gar nicht interessiert bin. Das ist nicht 'falsch', sondern bloß nicht
> auf alle denkbaren C-Implementierungen portabel (und vermutlich auch
> auf ein paar reale nicht). Es ist das auch nicht versehentlich,
> sondern mit voller Absicht.
Es ist auch voellig OK, hat bloss mit dem Topic von c.l.c nix zu tun.
On-Topic ist hingegen der Hinweis dass ein Programm mit einer Funktion
'strlcpy' den Standard verletzt, was praktisch gesehen aber oft OK ist.
> >> Falls die Aussage korret ist, 'beweist' sie, daß C für
> >> hardwarenahe Programmierung nicht zu gebrauchen ist,
> >
> > Standard C ist dafuer definitiv nicht zu gebrauchen, aus dem
> > simplen Grund das im Standard Hardware garnicht vorkommt. Keine
> > Ports, keine physischen RAM-Adressen, keine IRQs, nichts
> > dergleichen.
>
> Nein, FORTRAN ist dafür nicht zu gebrauchen, denn es hat ein
> vollkommen anderes Einsatzgebiet. C ist nicht 'FORTRAN für Doofe',
> sondern eine maschinennahe Sprache. Der Sinn von sowas ist nicht, daß
> man rasend schnell ablaufende Programme schreiben kann, sondern, daß
> man *maschinennah* damit programmieren kann, was für bestimmte
> Aufgaben notwendig und für andere sinnvoll ist.
Das ist korrekt fuer bestimmte C-Implementationen, nicht aber fuer C wie
im Standard beschrieben - und nur das ist strenggenommen On-Topic hier.
[snip]
> Leere Schleife in numerischen Programmen mögen ein Versehen sein (und
> somit 'optimierbar') aber in Gerätetreibern sind sie das iA nicht.
Und der C-Compiler weiss genau woher dass er gerade einen Treiber und
nicht ein numerisches Programm kompiliert? Oder darf man mit C keine
Numerik betreiben? Oder soll ein C-Compiler gar keine Optimierungen
versuchen duerfen (wieso nicht einfach die entsprechende Option
ausschalten wenn das ist was Du willst?)?
> >> Aus naheliegenden Gründen begünstigt das Leute, die immer noch
> >> am liebsten alles in Assembler schreiben würden und ist mir zB
> >> vollkommen egal. Falls der Standard nicht imstande ist, ein
> >> brauchbares Verhalten zu definieren, hat das Gremium versagt und
> >> nicht der Mensch, der dessen Hinweise notgedrungen ignoriert.
> >
> > Definiere brauchbares Verhalten fuer die Sprache C.
>
> Im konkreten Fall wäre das: Der Compiler übersetzt
>
> func(56);
>
> zu einem Aufruf der Funktion func(), denn warum ich die an dieser
> Stelle aufrufen wollte, kann er nicht wissen und es geht ihn auch
> überhaupt nichts an.
Er kann (unter Umstaenden) wissen dass der Aufruf keinen Effekt hat und
wenn Du ihm Optimierungen erlaubt hast geht es ihn was an - u.U.
> Falls der Compilerbauer das für einen Fehler
> hält, soll der Compiler bitte warnings produzieren. Das wäre sinnvoller
> als das hier:
>
> /home/rw/work/sentry/tmp/sentry_conf_file.o2: In function `start_sentry_conf_file':
> /home/rw/work/sentry/tmp/sentry_conf_file.o2(.text+0x5a): the use of
> `tempnam' is dangerous, better use `mkstemp'
Das musst Du aber konkret dem Linker-Bauer vorwerfen.
> void start_sentry_conf_file(void)
> {
> char *name;
> char const *path;
> u8 trials;
> int rc;
>
> trials = 0;
> path = getenv(CONFIG_PATH);
> while (1) {
> name = tempnam(path, "sny_");
> name || sys_die("start_sentry_conf_file", "tempnam", errno);
>
> rc = open(name, O_RDWR | O_CREAT | O_EXCL, 0600);
> if (rc != -1) break;
>
> free(name);
> ++trials;
> if (trials == 0) {
> notice("cannot create config file");
> exit(1);
> }
> }
>
> Offenbar bin ich nicht ganz planlos, wie die Autoren der
> Bibliotheksfunktion sich das vorgestellt hatten und die Autoren das
> Originals waren das sicher auch nicht.
Sicher. Aber vielleicht benutzt Du aus Versehen auch mal Software von so
einem planlosen Gesellen, oder Dein ISP, oder irgendwelche zufaelligen
Internet-User deren gehackte Rechner Dich dann DDOSen oder was weiss
ich.
Was ist denn so falsch an so einer fuer Dich leicht ignorierten Warnung?
Sicher. Das dauert länger als 'keine Zeit', wenn man sonstige Aspekte
außer acht läßt, man kann also (mit entsprechendem Aufwand)
ausrechnen, ab wievielen RPC-calls der Verzicht auf die Konvertierung
sich zu einem weiteren RPC-call aufsummiert hätte und konzeptuell
macht man davon unendlich viele.
> Und Deine Idee ist dann dass man im Protokoll eine (sicher nicht ganz
> triviale) Moeglichkeit implementiert um das Datenformat
> auszuhandeln?
Das ist nicht 'meine Idee', sondern eine aus einer nicht wirklich
erfolgreichen multi-vendor-Konvention bzgl DCE. Gerade durch 'Funk &
Fernsehn' gegeistert, weil IIRC auch von M$ verwendet.
[ strlcpy ]
> On-Topic ist hingegen der Hinweis dass ein Programm mit einer Funktion
> 'strlcpy' den Standard verletzt, was praktisch gesehen aber oft OK
> ist.
Lediglich ist er falsch. Ein Programm, dessen verhalten von Dingen
abhängt, die implementation defined, undefined oder unspecified sind
(also 'implementation defined') ist nicht mehr strictly conforming, dh
'not maximally portable among conforming implementations'.
>> Nein, FORTRAN ist dafür nicht zu gebrauchen, denn es hat ein
>> vollkommen anderes Einsatzgebiet. C ist nicht 'FORTRAN für Doofe',
>> sondern eine maschinennahe Sprache. Der Sinn von sowas ist nicht, daß
>> man rasend schnell ablaufende Programme schreiben kann, sondern, daß
>> man *maschinennah* damit programmieren kann, was für bestimmte
>> Aufgaben notwendig und für andere sinnvoll ist.
>
> Das ist korrekt fuer bestimmte C-Implementationen, nicht aber fuer C wie
> im Standard beschrieben -
Aber ganz sicher doch. ZB sind 'Unterroutinen' die einzigen
strukturierenden Elemente (typisch für Assemblersprachen), die Größe
der Basisintegers ist direkt an die Maschinenwortgröße gekoppelt und
es gibt keine Kontrollstrukturen außer bedingten Verzweigungen bis auf
ein einziges, recht primitives¹ generalisiertes Schleifenkonstrukt
(for (;;;)),
1) Es läßt sich trivial in C selber ausdrücken:
i = 0;
while (i < n) { ...; ...; ++i; }
Variablennamen referieren auf Speicherlokationen mit grundsätzlich
typlosem Inhalt etc.
> [snip]
>> Leere Schleife in numerischen Programmen mögen ein Versehen sein (und
>> somit 'optimierbar') aber in Gerätetreibern sind sie das iA nicht.
>
> Und der C-Compiler weiss genau woher dass er gerade einen Treiber und
> nicht ein numerisches Programm kompiliert? Oder darf man mit C keine
> Numerik betreiben? Oder soll ein C-Compiler gar keine Optimierungen
> versuchen duerfen
Er sollte keine Transformationen auf Quelltextebene durchführen (auch
keine verdeckten), außer es ist beweisbar, daß die tatsächlich eine
Verbesserung bewirken und nicht bloß eine Änderung. ZB ist für glibc
dokumentiert, das man std(in|out|err) wie normale Variablen behandeln
kann (also zB Zuweisungen zu machen). Das stimmt auch beinnahe, bloß
die Implementierung von puts verwendet 'aus einem unerfindlichen
Grund' eine Kopie des Originalwertes. Der offensichtliche Versuch,
diesen Bug zu umgehen, wären printf("string\n") anstelle von
puts("string") zu benutzen. Leider 'optimiert' gcc das aber zu
puts("string") ...
Ich halte es in jedem Fall für ziemlich gewagt, wenn ein Compiler
anfängt, Annahmen über den 'Sinn' von dem Code, den er übersetzt zu
machen, die über das hinausgehen, was im Programmquelltext explizit
ausgedrückt wurde. Woher will er die notwendigen Informationen
beziehen, um das allgemein entscheiden zu können?
> (wieso nicht einfach die entsprechende Option
> ausschalten wenn das ist was Du willst?)?
Klar. Ich kann das alles ausschalten und von Hand machen. Nur warum?
Weil manche Leute den Unterschied zwischen f(4) [Mathematik] und f(4)
[C] nicht verstehen können oder wollen? Mal ganz penetrant: »Kompetente
Leute brauchen keine Hilfsmittel, denn die sind ja kompetent [darin,
ohne welche zurechzukommen]«? Warum muß ich nicht als volatile
deklarierte nicht-auto Variablen immer noch von Hand in Register
schubsen, falls ich mehr als drei Operationen damit vornehmen möchte?
Warum muß ich überhaupt wissen, was ein 'Register' eigentlich ist?
>> > Definiere brauchbares Verhalten fuer die Sprache C.
>>
>> Im konkreten Fall wäre das: Der Compiler übersetzt
>>
>> func(56);
>>
>> zu einem Aufruf der Funktion func(), denn warum ich die an dieser
>> Stelle aufrufen wollte, kann er nicht wissen und es geht ihn auch
>> überhaupt nichts an.
>
> Er kann (unter Umstaenden) wissen dass der Aufruf keinen Effekt hat und
> wenn Du ihm Optimierungen erlaubt hast geht es ihn was an - u.U.
Der Aufruf hat aber immer wenigstens einen Effekt, nämlich er dauert
eine meßbare Zeit lang. sqrt(4) heißt nicht 'Quadratwurzel von vier'
sondern 'rufe die Funktion sqrt mit dem Argument
vier auf'. Zufälligerweise berechnet die Quadratwurzeln nach
irgendeinem stromlinienfrömigen Verfahren und macht keine
strukturierten Abfragen in Echtzeit.
>> /home/rw/work/sentry/tmp/sentry_conf_file.o2: In function `start_sentry_conf_file':
>> /home/rw/work/sentry/tmp/sentry_conf_file.o2(.text+0x5a): the use of
>> `tempnam' is dangerous, better use `mkstemp'
[...]
> Was ist denn so falsch an so einer fuer Dich leicht ignorierten
> Warnung?
Sie ist sachlich falsch.
>Rainer Weikusat <weik...@students.uni-mainz.de> wrote:
>
>> t0 = clock();
>>
>> sqrt(4);
>[...]
>> t0 = clock() - t0;
>> return t0;
>
>> Den 'Unterschied' kann ich nur dann nicht festellen, falls clock() bei
>> einer konkreten Implementierung immer -1 liefert.
>
>Wie stellst du einen 'Unterschied' zwischen "optimiert" und
>"nicht optimiert" fest, ohne das Programm zweimal mit
>unterschiedlichen Optimizer-Flags zu übersetzen? 'gcc -O0' ist
>eine andere C-Implementierung als 'gcc -O2'. Face it.
Und selbst wenn: Zwei Programmläufe haben unterschiedliche Eingangswerte
(clock() und time() sind im weitesten Sinne Eingabefunktionen), und
müssen demzufolge auch nicht die gleichen Ergebnisse liefern.
Ich wollte mehr darauf hinaus dass Sun-CPUs nicht direkt als
Superperformer bekannt sind, IOW zu jedem gegebenen Zeitpunkt in den
letzten Jahren waren die Konkurrenzprodukte schneller.
So lange die Konkurrenz mit den Umwandlungen einen RPC-Call schneller
abarbeitet als Sun-Hardware hat Sun nicht wirklich etwas gewonnen.
> > Und Deine Idee ist dann dass man im Protokoll eine (sicher nicht ganz
> > triviale) Moeglichkeit implementiert um das Datenformat
> > auszuhandeln?
>
> Das ist nicht 'meine Idee', sondern eine aus einer nicht wirklich
> erfolgreichen multi-vendor-Konvention bzgl DCE. Gerade durch 'Funk &
> Fernsehn' gegeistert, weil IIRC auch von M$ verwendet.
Also ich halte davon garnichts. Ist ja nicht als ob nicht schon genug
Bugs in Software waeren, alles noch zu verkomplizieren ist da nicht so
clever.
> [ strlcpy ]
>
> > On-Topic ist hingegen der Hinweis dass ein Programm mit einer Funktion
> > 'strlcpy' den Standard verletzt, was praktisch gesehen aber oft OK
> > ist.
>
> Lediglich ist er falsch. Ein Programm, dessen verhalten von Dingen
> abhängt, die implementation defined, undefined oder unspecified sind
> (also 'implementation defined') ist nicht mehr strictly conforming, dh
> 'not maximally portable among conforming implementations'.
OK, aber wer spricht das immer in voller Laenge aus?
> >> Nein, FORTRAN ist dafür nicht zu gebrauchen, denn es hat ein
> >> vollkommen anderes Einsatzgebiet. C ist nicht 'FORTRAN für Doofe',
> >> sondern eine maschinennahe Sprache. Der Sinn von sowas ist nicht, daß
> >> man rasend schnell ablaufende Programme schreiben kann, sondern, daß
> >> man *maschinennah* damit programmieren kann, was für bestimmte
> >> Aufgaben notwendig und für andere sinnvoll ist.
> >
> > Das ist korrekt fuer bestimmte C-Implementationen, nicht aber fuer C wie
> > im Standard beschrieben -
>
> Aber ganz sicher doch. ZB sind 'Unterroutinen' die einzigen
> strukturierenden Elemente (typisch für Assemblersprachen),
Hmm, hmm.
> die Größe der Basisintegers ist direkt an die Maschinenwortgröße
> gekoppelt
Das ist nicht ganz korrekt. Wenn die Wortgroesse zu klein ist kann das
so nicht gemacht werden.
> und
> es gibt keine Kontrollstrukturen außer bedingten Verzweigungen bis auf
> ein einziges, recht primitives¹ generalisiertes Schleifenkonstrukt
> (for (;;;)),
>
> 1) Es läßt sich trivial in C selber ausdrücken:
>
> i = 0;
> while (i < n) { ...; ...; ++i; }
While? Syntaktische Nettigkeiten fuer die korrekte Benutzung von if und
goto. Keine Verweichlichung! ;-)
> Variablennamen referieren auf Speicherlokationen mit grundsätzlich
> typlosem Inhalt etc.
Jede Menge Sprachen haben Variablen ohne RTTI, wieso ist das ein
besonderes Merkmal von C? Und wieso hat das was mit maschinennah zu tun,
hatten nicht die Lisp-Machines RTTI in Hardware oder zumindest ganz
ganz unten in der Software?
> > [snip]
> >> Leere Schleife in numerischen Programmen mögen ein Versehen sein (und
> >> somit 'optimierbar') aber in Gerätetreibern sind sie das iA nicht.
> >
> > Und der C-Compiler weiss genau woher dass er gerade einen Treiber und
> > nicht ein numerisches Programm kompiliert? Oder darf man mit C keine
> > Numerik betreiben? Oder soll ein C-Compiler gar keine Optimierungen
> > versuchen duerfen
>
> Er sollte keine Transformationen auf Quelltextebene durchführen (auch
> keine verdeckten), außer es ist beweisbar, daß die tatsächlich eine
> Verbesserung bewirken und nicht bloß eine Änderung.
Also gar keine, da sowas i.A. nicht beweisbar ist und man sowieso
erstmal "Verbesserung" exakt definieren muesste (viel Spass).
> ZB ist für glibc dokumentiert, das man std(in|out|err) wie normale
> Variablen behandeln kann (also zB Zuweisungen zu machen). Das stimmt
> auch beinnahe, bloß die Implementierung von puts verwendet 'aus einem
> unerfindlichen Grund' eine Kopie des Originalwertes. Der
> offensichtliche Versuch, diesen Bug zu umgehen, wären
> printf("string\n") anstelle von puts("string") zu benutzen. Leider
> 'optimiert' gcc das aber zu puts("string") ...
Das ist aergerlich aber weniger ein Problem des Compilers als der glibc.
> Ich halte es in jedem Fall für ziemlich gewagt, wenn ein Compiler
> anfängt, Annahmen über den 'Sinn' von dem Code, den er übersetzt zu
> machen, die über das hinausgehen, was im Programmquelltext explizit
> ausgedrückt wurde. Woher will er die notwendigen Informationen
> beziehen, um das allgemein entscheiden zu können?
Aus der Sprachdefinition z.B. Das Programm
void foo() {
int cnt;
for ( cnt=0; cnt < 10000; cnt++ )
/*EMPTY*/ ;
}
int main( void ) {
foo();
return 0;
}
dient offensichtlich dazu die Zeit zum Inkrementieren eines ints zu
messen, mit einer Stoppuhr vermutlich.
Sowas ist aber fuer C irrelevant da es keine Annahmen wie die Existenz
von Stoppuhren macht - es gibt AFAIK noch nicht mal die Aussage dass die
Ausfuehrung eines Programms ueberhaupt eine endliche Zeit braucht.
Der Compiler sieht bloss dass da eine Variable hochgezaehlt aber
ansonsten nie verwendet wird und laesst das weg da es die dokumentierten
Effekte des Programms nicht veraendert (Ablaufzeit gehoert ja nicht
dazu).
Das ist einfach eine Folge davon dass Compiler i.A. auf Geschwindigkeit
optimieren (sollen).
> > (wieso nicht einfach die entsprechende Option
> > ausschalten wenn das ist was Du willst?)?
>
> Klar. Ich kann das alles ausschalten und von Hand machen. Nur warum?
> Weil manche Leute den Unterschied zwischen f(4) [Mathematik] und f(4)
> [C] nicht verstehen können oder wollen? Mal ganz penetrant: »Kompetente
> Leute brauchen keine Hilfsmittel, denn die sind ja kompetent [darin,
> ohne welche zurechzukommen]«?
Das ist genau der springende Punkt. Wenn alle Leute kompetent waeren
waere die Welt eine bessere, leider sind fast(?) alle Leute eben nicht
kompetent, zumindest nicht auf dem Level und nicht auf allen Gebieten.
> Warum muß ich nicht als volatile deklarierte nicht-auto Variablen
> immer noch von Hand in Register schubsen, falls ich mehr als drei
> Operationen damit vornehmen möchte?
Keine Ahnung, aber es sollte mich schwer wundern wenn das bei allen
Compilern so waere - taugt also nicht als Vorwurf gegen alle Compiler.
Letztendlich ist C eben nicht Assembler und man zahlt fuer den
syntaktischen Kokolores einen Preis. Wer es nicht mag findet den
Assembler dort ------------->.
> Warum muß ich überhaupt wissen, was ein 'Register' eigentlich ist?
Du musst garnicht, Du willst. Wenn Du es nicht wissen wuerdest, wuerdest
Du Dich hier auch nicht beschweren koennen dass der Compiler Variable x
nicht in ein Register gepackt hat wie Du es gern wolltest.
Nicht dass IMHO ein gewisses Wissen ueber die tatsaechliche Funktion von
CPUs nicht sehr wuenschenswert waere.
> >> > Definiere brauchbares Verhalten fuer die Sprache C.
> >>
> >> Im konkreten Fall wäre das: Der Compiler übersetzt
> >>
> >> func(56);
> >>
> >> zu einem Aufruf der Funktion func(), denn warum ich die an dieser
> >> Stelle aufrufen wollte, kann er nicht wissen und es geht ihn auch
> >> überhaupt nichts an.
> >
> > Er kann (unter Umstaenden) wissen dass der Aufruf keinen Effekt hat und
> > wenn Du ihm Optimierungen erlaubt hast geht es ihn was an - u.U.
>
> Der Aufruf hat aber immer wenigstens einen Effekt, nämlich er dauert
> eine meßbare Zeit lang.
Wie gesagt, endliche Laufzeiten stehen AFAIK nicht im Standard.
> sqrt(4) heißt nicht 'Quadratwurzel von vier'
> sondern 'rufe die Funktion sqrt mit dem Argument
> vier auf'.
Es wuerde das letztere heissen wenn sqrt keine Standardfunktion waere.
Da es eine ist heisst es tatsaechlich Quadratwurzel von 4 was der
Compiler wissen kann oder auch nicht.
> Zufälligerweise berechnet die Quadratwurzeln nach
> irgendeinem stromlinienfrömigen Verfahren und macht keine
> strukturierten Abfragen in Echtzeit.
Der Compiler kann sehr wohl "sqrt(4)" einfach durch "2.0" ersetzen, eben
weil er die Funktion und ihre Effekte kennen darf. Ganz genauso wie er
auch "3 * 3 - 2" durch "7" ersetzen darf obwohl Du vielleicht damit
Laufzeiten fuer die Operationen messen wolltest.
> >> /home/rw/work/sentry/tmp/sentry_conf_file.o2: In function `start_sentry_conf_file':
> >> /home/rw/work/sentry/tmp/sentry_conf_file.o2(.text+0x5a): the use of
> >> `tempnam' is dangerous, better use `mkstemp'
>
> [...]
>
> > Was ist denn so falsch an so einer fuer Dich leicht ignorierten
> > Warnung?
>
> Sie ist sachlich falsch.
Eine Compiler-Message ist keine wissenschaftliche Aussage, mit Beweis
und allem Brimborium.
Es verkompliziert sich aber gar nichts, im Gegenteil. Der Sender muß
nie Daten konvertieren, der Empfänger nur, falls der Sender nicht sein
natives Datenformat benutzt.
[maschinennahe Sprachen/ C]
>> die Größe der Basisintegers ist direkt an die Maschinenwortgröße
>> gekoppelt
>
> Das ist nicht ganz korrekt. Wenn die Wortgroesse zu klein ist kann das
> so nicht gemacht werden.
Ich meine mich allerdings an 'an int shall have the size that is most
natural for the machine' (oä) erinnern zu können. Eine
Implementierung, die ein shall-constraint nicht einhält, bewegt sich
mittig in dem was laut C 'undefiniert' ist. Strengenommen ist das eine
Umgebung, die einen Teil von C emuliert, aber kein C.
>> Variablennamen referieren auf Speicherlokationen mit grundsätzlich
>> typlosem Inhalt etc.
>
> Jede Menge Sprachen haben Variablen ohne RTTI, wieso ist das ein
> besonderes Merkmal von C?
Das hier ist ein besonderes Merkmal von C:
signed char x;
unsigned short y;
x = -1;
y = x + 512;
Eine Integer-Variable entspricht einem Container einer bestimmten
Größe, der eine mehr oder minder willkürlich Untermenge der
natürlichen Zahlen in Binärdarstellung beinhalten. Falls ich den Wert
der Variablen benutze, wird er zu int promoted (vereinfach), vulgo:
Auf die Maschinenwortgröße expandiert (weil mutmaßlich in ein Register
geladen), dann wird irgendeine Operation damit durchgeführt und das
Resultat wird im Falle einer Zuweisung transparent an einen anderen
Containertyp angepasst. Auch wenn sich dadurch dadurch ggf der Wert
ändert:
unsigned short x = 0xffff;
unsigned char y;
y = x;
Das ist sehr bequem, wenn man viel mit Bitmustern hantieren muß, die
sich wenigstens grundsätzlich in Form von chars repäsentieren lassen,
aber für höhere Programmiersprachen eher ungewöhnlich. Dort wird
häufig eine 'mathematischere' Definition von 'Zuweisung' benutzt, die
zB folgende Eigenschaft hat:
y = x => y == x
Diese Eigenschaft ist in C nicht gegeben und falls man sie als
grundlegend ansieht, hält man das für einen Fehler :->. Was an C auch
noch dankenswert hervorzuheben ist, ist die faktische Abwesenheit von
Aufzählungstypen, außer als selbstausgesuchter Fiktion. Das bedeutet
zB, das Funktionen Integerkonstanten zurückgeben können, die in
unterschiedlichen Headern definiert wurden, ohne das man den Compiler
mit einer Brechtstange dazu nötigen muß, diesen 'Typfehler' zu
ignorieren.
> Und wieso hat das was mit maschinennah zu tun,
> hatten nicht die Lisp-Machines RTTI in Hardware oder zumindest ganz
> ganz unten in der Software?
Lisp ist auch eine ziemlich typloses Sprache ... :-).
>> Er sollte keine Transformationen auf Quelltextebene durchführen (auch
>> keine verdeckten), außer es ist beweisbar, daß die tatsächlich eine
>> Verbesserung bewirken und nicht bloß eine Änderung.
>
> Also gar keine, da sowas i.A. nicht beweisbar ist und man sowieso
> erstmal "Verbesserung" exakt definieren muesste (viel Spass).
Darauf wollte ich hinaus. Dh er sollte keine Funktionen ungebeten
inline expandieren und erst recht keine Aufrufe wechselseitig
ersetzen.
> void foo() {
> int cnt;
> for ( cnt=0; cnt < 10000; cnt++ )
> /*EMPTY*/ ;
> }
>
> int main( void ) {
> foo();
> return 0;
> }
>
[...]
> Der Compiler sieht bloss dass da eine Variable hochgezaehlt aber
> ansonsten nie verwendet wird und laesst das weg da es die dokumentierten
> Effekte des Programms nicht veraendert (Ablaufzeit gehoert ja nicht
> dazu).
Es ist von der Implementierung abhängig, ob sie 'intrinsically' meßbar
ist.
> Das ist einfach eine Folge davon dass Compiler i.A. auf Geschwindigkeit
> optimieren (sollen).
'Auf Geschwindigkeit optimiert' wäre das, wenn der Compiler wegen
fehlendem loop-body erkennen würde, daß er das als
cnt = 10000;
do { --cnt; } while (cnt);
übersetzen könnte (entsprechende Maschinenbefehle vorausgesetzt). Wenn
ich den Code weglasse, wird er nicht ausgeführt. Jetzt stellt sich
allerdings die Frage: Warum stand er da? (Antwort: Weil das ein blödes
Beispiel ist ;-). Es ist inconceivable, das 'dead code' gleichzeitig
dead und performancekritisch ist, dh ich kann hier einfach keinen
denkbaren Nutzen erkennen.
> Der Compiler kann sehr wohl "sqrt(4)" einfach durch "2.0" ersetzen, eben
> weil er die Funktion und ihre Effekte kennen darf.
Sicher kann er. Nur warum sollte er? Aus pragmatischen Gründen würde
ich Literale nur in Ausnahmefällen direkt in den Quellcode schreiben.
>> >> /home/rw/work/sentry/tmp/sentry_conf_file.o2: In function `start_sentry_conf_file':
>> >> /home/rw/work/sentry/tmp/sentry_conf_file.o2(.text+0x5a): the use of
>> >> `tempnam' is dangerous, better use `mkstemp'
>>
>> [...]
>>
>> > Was ist denn so falsch an so einer fuer Dich leicht ignorierten
>> > Warnung?
>>
>> Sie ist sachlich falsch.
>
> Eine Compiler-Message ist keine wissenschaftliche Aussage,
Using filenames generated by ... can be hazardous.
Man könnte sogar den überdramatischen Tonfall beibehalten.
>Mathias Grimmberger <mg...@zaphod.sax.de> writes:
>
>>> In short garantiert das, das Sun-Rechner (traditionell big-endian)
>>> immer einen höheren NFS-Durchsatz erzielen werden, als andere, was den
>>> Erfindern dieser Repräsentation nicht ganz unlieb gewesen sein
>>> dürfte.
>>
>> Hmm, hmm. Du meinst ernsthaft dass Sun einen echten Vorteil hat weil
>> ein paar Header-Felder umgewandelt werden muessen?
>
> Sicher. Das dauert länger als 'keine Zeit', wenn man sonstige Aspekte
> außer acht läßt, man kann also (mit entsprechendem Aufwand)
> ausrechnen, ab wievielen RPC-calls der Verzicht auf die Konvertierung
> sich zu einem weiteren RPC-call aufsummiert hätte und konzeptuell
> macht man davon unendlich viele.
Ich weiß ja nicht, wie es Dir geht, aber bei mir (und zumindest den
meisten anderen Endanwendern auch) ist das Nadelöhr die Anbindung und
nicht CPU leistung. Und 1000 vs. 1001 RPC-Call fällt dann auch nicht
wirklich ins Gewicht.
>> Und Deine Idee ist dann dass man im Protokoll eine (sicher nicht ganz
>> triviale) Moeglichkeit implementiert um das Datenformat
>> auszuhandeln?
>
> Das ist nicht 'meine Idee', sondern eine aus einer nicht wirklich
> erfolgreichen multi-vendor-Konvention bzgl DCE. Gerade durch 'Funk &
> Fernsehn' gegeistert, weil IIRC auch von M$ verwendet.
Und weil M$ verwendet ist gut oder was?
> [ strlcpy ]
>
>> On-Topic ist hingegen der Hinweis dass ein Programm mit einer Funktion
>> 'strlcpy' den Standard verletzt, was praktisch gesehen aber oft OK
>> ist.
>
> Lediglich ist er falsch. Ein Programm, dessen verhalten von Dingen
> abhängt, die implementation defined, undefined oder unspecified sind
> (also 'implementation defined') ist nicht mehr strictly conforming, dh
> 'not maximally portable among conforming implementations'.
Ein Programm, daß nicht strictly conforming ist, interessiert in dieser
Gruppe nicht, und wenn jemand sowas postet, dann wird darauf hingewiesen.
Entweder mit einem Zitat aus dem Standard, oder mit dem dritten Weltkrieg
oder mit gelben Warzenschweinen. In jedem Fall ist solch ein Hinweis
absolut richtig.
>>> Nein, FORTRAN ist dafür nicht zu gebrauchen, denn es hat ein
>>> vollkommen anderes Einsatzgebiet. C ist nicht 'FORTRAN für Doofe',
>>> sondern eine maschinennahe Sprache. Der Sinn von sowas ist nicht, daß
>>> man rasend schnell ablaufende Programme schreiben kann, sondern, daß
>>> man *maschinennah* damit programmieren kann, was für bestimmte
>>> Aufgaben notwendig und für andere sinnvoll ist.
>>
>> Das ist korrekt fuer bestimmte C-Implementationen, nicht aber fuer C
>> wie im Standard beschrieben -
>
> Aber ganz sicher doch. ZB sind 'Unterroutinen' die einzigen
> strukturierenden Elemente (typisch für Assemblersprachen), die Größe
> der Basisintegers ist direkt an die Maschinenwortgröße gekoppelt und
> es gibt keine Kontrollstrukturen außer bedingten Verzweigungen bis auf
> ein einziges, recht primitives¹ generalisiertes Schleifenkonstrukt
> (for (;;;)),
>
> 1) Es läßt sich trivial in C selber ausdrücken:
>
> i = 0;
> while (i < n) { ...; ...; ++i; }
>
> Variablennamen referieren auf Speicherlokationen mit grundsätzlich
> typlosem Inhalt etc.
Wenn Du den Sinn hinter dem Standard nicht verstehst, solltest Du Dir
überlegen, den Beruf zu wechseln. Und wenn Du den Sinn verstehst, diesen
aber nicht akzeptieren kannst, dann verlasse doch bitte diese Gruppe. Wenn
beides nicht zutrifft, dann erkläre doch mal bitte, was Du hiermit
aussagen willst.
>> [snip]
>>> Leere Schleife in numerischen Programmen mögen ein Versehen sein (und
>>> somit 'optimierbar') aber in Gerätetreibern sind sie das iA nicht.
>>
>> Und der C-Compiler weiss genau woher dass er gerade einen Treiber und
>> nicht ein numerisches Programm kompiliert? Oder darf man mit C keine
>> Numerik betreiben? Oder soll ein C-Compiler gar keine Optimierungen
>> versuchen duerfen
>
> Er sollte keine Transformationen auf Quelltextebene durchführen (auch
> keine verdeckten), außer es ist beweisbar, daß die tatsächlich eine
> Verbesserung bewirken und nicht bloß eine Änderung. ZB ist für glibc
> dokumentiert, das man std(in|out|err) wie normale Variablen behandeln
> kann (also zB Zuweisungen zu machen). Das stimmt auch beinnahe, bloß
> die Implementierung von puts verwendet 'aus einem unerfindlichen
> Grund' eine Kopie des Originalwertes. Der offensichtliche Versuch,
> diesen Bug zu umgehen, wären printf("string\n") anstelle von
> puts("string") zu benutzen. Leider 'optimiert' gcc das aber zu
> puts("string") ...
Der rinzige offensichtlich richtige Schritt wäre es, einen Bug-Report an
die Macher der glibc zu schreiben, ggf. mit einem Patch der den Fehler
beseitigt, und dann braucht man auch keine Würgarounds. Das Verhalten des
Compilers ist absolut ok, denn er ersetzt einen langsamen funktionsaufruf
durch einen schnelleren, und spart ein Byte. Und wenn Du wirklich die
Funktion printf aufrufen willst, schlage ich dir einen Wrapper als
Würgaround vor, z.B. rwputs oder so.
> Ich halte es in jedem Fall für ziemlich gewagt, wenn ein Compiler
> anfängt, Annahmen über den 'Sinn' von dem Code, den er übersetzt zu
> machen, die über das hinausgehen, was im Programmquelltext explizit
> ausgedrückt wurde. Woher will er die notwendigen Informationen
> beziehen, um das allgemein entscheiden zu können?
Der Compiler hat alles wissen, was er benötigt, um printf("@irgendwas@\n")
in puts("@irgendwas@") zu ändern, und daß Du mit einer kaputten Library
arbeitest ist ja nun wirklich nicht die Schuld des Compilers.
>> (wieso nicht einfach die entsprechende Option
>> ausschalten wenn das ist was Du willst?)?
>
> Klar. Ich kann das alles ausschalten und von Hand machen. Nur warum?
> Weil manche Leute den Unterschied zwischen f(4) [Mathematik] und f(4)
> [C] nicht verstehen können oder wollen?
Was genau hast Du an der "AS-IF"-Regel nicht verstanden?
> Mal ganz penetrant: »Kompetente Leute brauchen keine Hilfsmittel, denn
> die sind ja kompetent [darin, ohne welche zurechzukommen]«? Warum muß
> ich nicht als volatile deklarierte nicht-auto Variablen immer noch von
> Hand in Register schubsen, falls ich mehr als drei Operationen damit
> vornehmen möchte?
Schreib einen Compiler, der sowas alleine schafft, anstatt Dich darüber
zu beschweren, daß der, den Du verwendest es nicht kann.
> Warum muß ich überhaupt wissen, was ein 'Register' eigentlich ist?
Wer sagt denn, daß Du das must? Lass Die Variable doch im Arbeitsspeicher.
Ist absolut Standard-Konform.
>>>> Definiere brauchbares Verhalten fuer die Sprache C.
>>>
>>> Im konkreten Fall wäre das: Der Compiler übersetzt
>>>
>>> func(56);
>>>
>>> zu einem Aufruf der Funktion func(), denn warum ich die an dieser
>>> Stelle aufrufen wollte, kann er nicht wissen und es geht ihn auch
>>> überhaupt nichts an.
>>
>> Er kann (unter Umstaenden) wissen dass der Aufruf keinen Effekt hat und
>> wenn Du ihm Optimierungen erlaubt hast geht es ihn was an - u.U.
>
> Der Aufruf hat aber immer wenigstens einen Effekt, nämlich er dauert
> eine meßbare Zeit lang.
Zitiere bitte die Stelle im Standard, die einen Zeitverbrauch durch den
Aufruf einer Funktion garantiert.
> sqrt(4) heißt nicht 'Quadratwurzel von vier' sondern 'rufe die Funktion
> sqrt mit dem Argument vier auf'.
Zeige mir bitte die Stelle im Standard, der diese Behauptung unterstützt.
>>> /home/rw/work/sentry/tmp/sentry_conf_file.o2: In function
>>> `start_sentry_conf_file':
>>> /home/rw/work/sentry/tmp/sentry_conf_file.o2(.text+0x5a): the use of
>>> `tempnam' is dangerous, better use `mkstemp'
>
>[...]
>
>> Was ist denn so falsch an so einer fuer Dich leicht ignorierten
>> Warnung?
>
>Sie ist sachlich falsch.
Was genau ist denn daran falsch?
> Jens Schweikhardt <use...@schweikhardt.net> writes:
>> Rainer Weikusat <weik...@students.uni-mainz.de> wrote
>
> [ undefined behaviour ]
>
>>#> Dann hast Du ein deutliches Problem mit logischem Denken. Wenn etwas
>>#> undefiniert gelassen wird,
>>#
>># ... dann wird es *undefiniert* gelassen, was etwas anderes ist, als
>># *beliebig definiert*.
>>
>> Ja. Und undefiniert heißt undefiniert heißt undefiniert.
>
> Du wiederholst mich. Wofür? 'Undefiniert' heißt in C exakt 'der
> Standard macht keine Aussage dazu', nicht
> $willkürlicher_blödsinn_der_mir_gerade_in_den_sinn_kam.
Aber der Poster erwartet $irgend_etwas_was_er_gerade_braucht, und der
Hinweis, daß auch $willkürlicher_blödsinn_der_mir_gerade_in_den_sinn_kam
passieren kann, ist deswegen so wichtig, damit die Brisanz des Problem
richtig 'rüber kommt.
> Für alle praktischen Zwecke bedeutet 'undefined' 'implementation
> defined' und die konkrete Reaktion einer Implementierung läßt sich
> auch ermitteln.
Ist aber 1. nicht vom Standard gedeckt, 2. dadurch hier OffTopic, und 3.
nicht das, was der Poster will (wir schreiben ja wohl hoffentlich nicht
nur in C, weil's cool ist, sondern auch, weil wir möglichst portabel sein
wollen).
> Als Beispiel verweise ich auf das 'Endianess bei Bitfeldern'-Posting von
> vor einer Weile. Der C-Standard gestattet es sogar ausdrücklich, das
> Programme solche Effekte ausnutzen ('A conforming programm is something
> accepted by a conforming implementation').
Ein "conforming program" ist hier solange OffTopic, bis da ein strictly
dabei kommt.
> Vgl Lisp: Wenn dort etwas als 'is an error' definiert ist, muß eine
> Implementierung das zwar nicht erkennen, aber sie darf kein sinnvolles
> dokumentiertes Verhalten dafür haben.
Also gibt es dort auch den Unterschied zwischen conforming und strictly
conforming, nur darf das conforming nicht dokumentiert sein. Toller
Fortschritt.
> C-Implementierungen dürfen das auch für 'undefined behaviour'
> denn ist undefined (undefined, undefined) und nicht wrong (wrong,
> wrong), falls das in Kleinkindersprache evtl besser ankommt.
Das problem mit undefined, unspecified und implementation defined ist
doch, daß es jede implementation anders machen darf, und deswegen sollte
man sowas nicht verwenden, zumindest nicht, solange man protabel sein will
(und wenn man das nicht will, ist man hier OffTopic).
> Es wird sogar ausdrücklich zwischen 'errnous usage' und 'undefined
> behaviour' unterschieden: Ersteres ist eine Teilmenge von letzterem.
Ja und?
>># Eine Tatsache ist vielmehr,
>># das Compiler Programm anhand statischer Regeln übersetzen (dito für
>># Interpreter) und dazu gehört zB eine Grammatik, nach deren Maßgabe
>># man beurteilen, was eine grammatisch wohlgeformte Formulierung ist
>># und was nicht. Zb ist 'Das Bankgebäude wirbelte auf dem Absatz herum
>># und zog seinen Revolver' ein korrekter deutscher Satz ohne Sinn.
>># Analog gilt das für a[++i] = i++ in C. Das wäre eine übliche
>># linguistische Betrachtungsweise für Sprachen.
>>
>> Wie Du das betrachtest und nennst ist mir egal.
>
> Das nenne allerdings nicht ich so, sondern ein nennenswerter Korpus an
> sprachwissenschaftlicher Fachliteratur und C ist genauso eine von
> Menschen geschaffene Sprache wie Deutsch oder Esperanto. Solange Du
> nichts besseres als 'Mir doch egal' zu bieten hast, mußt Du Dir da den
> Vorwurf der Unsachlichkeit, des 'Füße aufstampfens', um in Deiner
> Diktion zu bleiben, gefallen lassen.
Nenne mir einen Satz in C und ich sage Dir, ob er korrekt ist oder nicht.
Vergleiche haben die Eigenschaft, nicht 100% übereinzustimmen. Bei einem
Satz in einer natürlichen Sprache, gibt es erstmal die Lexik (kann jedes
billige Rechtschreibprüfprogramm Checken, sofern das Wörterbuch ausreicht,
einziges Problem sind hier Eigennamen und Kunstbegriffe), dann kommt
die Syntax, dann die Grammatik, und wenn diese Hürden genommen wurden,
kann man die semantische Korrektheit unter die Lupe nehmen. Ein Aufsatz
ist nur dann ein korrekter Aufsatz, wenn auch die Semantik eines jeden
Satzes korrekt ist.
Ein C-Programm besteht nicht aus Sätzen, sondern aus Expressions. Jede
Expression kann auf syntaktische Korrektheit überprüft werden. Ob ++i=0;
da rausfliegt ist eine Frage für sich, spätestens im nächsten Schritt, die
Gramatik zu überprüfen, fliegt dieser Ausdruck raus. a[i++]=++i; fliegt
möglicherweise hier noch nicht raus, wenn man aber noch die Semantik
überprüft, fliegt auch sowas raus.
Und was dann übrig bleibt, sollte nurnoch Runtime-Errors enthalten.
>Mathias Grimmberger <mg...@zaphod.sax.de> writes:
>> Rainer Weikusat <weik...@students.uni-mainz.de> writes:
>>> Das ist nicht 'meine Idee', sondern eine aus einer nicht wirklich
>>> erfolgreichen multi-vendor-Konvention bzgl DCE. Gerade durch 'Funk &
>>> Fernsehn' gegeistert, weil IIRC auch von M$ verwendet.
>>
>> Also ich halte davon garnichts. Ist ja nicht als ob nicht schon genug
>> Bugs in Software waeren, alles noch zu verkomplizieren ist da nicht so
>> clever.
>
> Es verkompliziert sich aber gar nichts, im Gegenteil. Der Sender muß
> nie Daten konvertieren, der Empfänger nur, falls der Sender nicht sein
> natives Datenformat benutzt.
Also beim Senden einmal hton() und beim Empfangen einmal ntoh() zu machen
ist doch wohl einfacher, als ein unbekannted Datenformat ins native
Format zu übersetzen. Und wie war das? if (format!=NATIVE)
value=mknative(value); wo dann die Abfrage fünf mal länger dauert, als der
Aufruf von ntoh? Außerdem kann man für hton und ntoh jeweil eine
Maschienensprachen instruktion einführen. Wenn man aber plötzlich viele
verschiedene Formate handlen können muß, fällt die Option
Maschienenspracheninstruktion auch flach.
>[maschinennahe Sprachen/ C]
>
>>> die Größe der Basisintegers ist direkt an die Maschinenwortgröße
>>> gekoppelt
>>
>> Das ist nicht ganz korrekt. Wenn die Wortgroesse zu klein ist kann das
>> so nicht gemacht werden.
>
> Ich meine mich allerdings an 'an int shall have the size that is most
> natural for the machine' (oä) erinnern zu können. Eine
> Implementierung, die ein shall-constraint nicht einhält, bewegt sich
> mittig in dem was laut C 'undefiniert' ist. Strengenommen ist das eine
> Umgebung, die einen Teil von C emuliert, aber kein C.
Was ist denn sie "size that is most natural for the machine" bei der ia32
Architektur? 8 Bit (ah, al, ...), 16 Bit (ax, bx, ...) oder 32 Bit (eax,
ebx, ...)? Zumindest was die ia32 Architektur angeht, sind alle drei
größen gleich "natural for the machine".
> signed char x;
> unsigned short y;
>
> x = -1;
> y = x + 512;
Entweder y = 511 oder Trap. Was willst Du?
> unsigned short x = 0xffff;
> unsigned char y;
>
> y = x;
y ist doch sowieso zu klein...
> y = x => y == x
int x=5,y;
y=x;
assert(x==y);
> Diese Eigenschaft ist in C nicht gegeben
Nee?
Wenn Du natürlich Äpfel mit Birnen vergleichst ...
>>> Er sollte keine Transformationen auf Quelltextebene durchführen (auch
>>> keine verdeckten), außer es ist beweisbar, daß die tatsächlich eine
>>> Verbesserung bewirken und nicht bloß eine Änderung.
>>
>> Also gar keine, da sowas i.A. nicht beweisbar ist und man sowieso
>> erstmal "Verbesserung" exakt definieren muesste (viel Spass).
>
> Darauf wollte ich hinaus. Dh er sollte keine Funktionen ungebeten
> inline expandieren und erst recht keine Aufrufe wechselseitig
> ersetzen.
Dann sag das dem Compiler, und er tut es nicht. Wundere Dich dann aber
auch nicht darüber, daß Deine Programme 10 mal langsamer werden.
>> void foo() {
>> int cnt;
>> for ( cnt=0; cnt < 10000; cnt++ )
>> /*EMPTY*/ ;
>> }
>>
>> int main( void ) {
>> foo();
>> return 0;
>> }
>>
Schon mal an ein Assembler-Inline gedacht?
>> Der Compiler sieht bloss dass da eine Variable hochgezaehlt aber
>> ansonsten nie verwendet wird und laesst das weg da es die
>> dokumentierten Effekte des Programms nicht veraendert (Ablaufzeit
>> gehoert ja nicht dazu).
>
> Es ist von der Implementierung abhängig, ob sie 'intrinsically' meßbar
> ist.
Und ich dache, wir hätten uns geeinigt, das Wort Intrinsic nicht zu
verwenden ...
BTW: Garantien die der Standard (nicht) macht, sind nicht von der
Implementation abhängig.
>> Das ist einfach eine Folge davon dass Compiler i.A. auf Geschwindigkeit
>> optimieren (sollen).
>
> 'Auf Geschwindigkeit optimiert' wäre das, wenn der Compiler wegen
> fehlendem loop-body erkennen würde, daß er das als
>
> cnt = 10000;
ACK.
> do { --cnt; } while (cnt);
Warum das? Nicht nur, daß das ein Fehler ist, nein, die Schleife ist auch
noch sinnfrei.
>> Der Compiler kann sehr wohl "sqrt(4)" einfach durch "2.0" ersetzen,
>> eben weil er die Funktion und ihre Effekte kennen darf.
>
> Sicher kann er. Nur warum sollte er?
<skeptisch>Weil es schneller ist?</skeptisch>
> Aus pragmatischen Gründen würde ich Literale nur in Ausnahmefällen
> direkt in den Quellcode schreiben.
Davon spricht hier ja auch keiner. Aber der Compiler generiert ja auch
kein Quellcode.
>>>>> /home/rw/work/sentry/tmp/sentry_conf_file.o2: In function
>>>>> `start_sentry_conf_file':
>>>>> /home/rw/work/sentry/tmp/sentry_conf_file.o2(.text+0x5a): the use
>>>>> of `tempnam' is dangerous, better use `mkstemp'
>>>
>>> [...]
>>>
>>>> Was ist denn so falsch an so einer fuer Dich leicht ignorierten
>>>> Warnung?
>>>
>>> Sie ist sachlich falsch.
>>
>> Eine Compiler-Message ist keine wissenschaftliche Aussage,
>
> Using filenames generated by ... can be hazardous.
>
> Man könnte sogar den überdramatischen Tonfall beibehalten.
Ich denke, daß diese Funktion häufig falsch verwendet wird, und vor allen,
daß dabei immer gleich ein riesen Schaden entsteht, wenn man es macht. Ich
empfinde es als vorteilhaft, eine Umgebung zu benutzen, die mich vor
solchen sachen warnt. BTW: Du könnstest Dir einiges an Verrenkungen
sparen, würdest Du einfach eine andere Funktion als tempnam verwenden.
Eventuell gibt es bald ja sogar eine Betriebssystemfunkion, die mkstemp
erledigt. Dann würdest Du also eine komplette Funktion geschrieben haben,
für eine Aufgabe, die Das OS für Dich erledigt. Herzlichen Glückwunsch.
Beim Senden gar nichts zu tun und beim Empfangen ggf die Endianness
umzustellen erfordert ein Flag im Datensatz und nicht mehr Code, als
andernfalls auch gebraucht würde. Erzähle bitte den gewesenen
Mitgliedern der OSF (ua IBM, MIT und HP), das ihre Ingenieure/
Wissenschaftler alles Idioten sind.
>> Ich meine mich allerdings an 'an int shall have the size that is most
>> natural for the machine' (oä) erinnern zu können. Eine
>> Implementierung, die ein shall-constraint nicht einhält, bewegt sich
>> mittig in dem was laut C 'undefiniert' ist. Strengenommen ist das eine
>> Umgebung, die einen Teil von C emuliert, aber kein C.
>
> Was ist denn sie "size that is most natural for the machine" bei der ia32
> Architektur? 8 Bit (ah, al, ...), 16 Bit (ax, bx, ...) oder 32 Bit (eax,
> ebx, ...)? Zumindest was die ia32 Architektur angeht, sind alle drei
> größen gleich "natural for the machine".
Sie sind es nicht. Wortgröße für ia32 sind (Überraschung!) 32 Bit.
>> signed char x;
>> unsigned short y;
>>
>> x = -1;
>> y = x + 512;
>
> Entweder y = 511 oder Trap
Es kann hier kein trap geben.
>> unsigned short x = 0xffff;
>> unsigned char y;
>>
>> y = x;
>
>> y = x => y == x
>
>> Diese Eigenschaft ist in C nicht gegeben
>
> Nee?
Nein. Gegenbeispiel steht oben.
>> Darauf wollte ich hinaus. Dh er sollte keine Funktionen ungebeten
>> inline expandieren und erst recht keine Aufrufe wechselseitig
>> ersetzen.
>
> Dann sag das dem Compiler, und er tut es nicht. Wundere Dich dann aber
> auch nicht darüber, daß Deine Programme 10 mal langsamer werden.
Zehnmal langsamer als was?
>>> Der Compiler sieht bloss dass da eine Variable hochgezaehlt aber
>>> ansonsten nie verwendet wird und laesst das weg da es die
>>> dokumentierten Effekte des Programms nicht veraendert (Ablaufzeit
>>> gehoert ja nicht dazu).
>>
>> Es ist von der Implementierung abhängig, ob sie 'intrinsically' meßbar
>> ist.
>
> Und ich dache, wir hätten uns geeinigt, das Wort Intrinsic nicht zu
> verwenden ...
Das ist zunächst mal ein englisches Adjektiv mit einer bestimmten
Bedeutung.
>> 'Auf Geschwindigkeit optimiert' wäre das, wenn der Compiler wegen
>> fehlendem loop-body erkennen würde, daß er das als
>>
>> cnt = 10000;
>> do { --cnt; } while (cnt);
>
> Warum das? Nicht nur, daß das ein Fehler ist, nein, die Schleife ist auch
> noch sinnfrei.
Die Schleife war vorher auch schon sinnfrei, aber weil der (in diesem
Fall leere) Schleifekörper erkennbar nicht von der Zählrichtung
abhängt, kann man sie umdrehen.
i = 0;
do { x[i] = y[i] } while (++i < 10000);
i = 10000;
do { --i; x[i] = y[i]; } while (i);
>>> Der Compiler kann sehr wohl "sqrt(4)" einfach durch "2.0" ersetzen,
>>> eben weil er die Funktion und ihre Effekte kennen darf.
>>
>> Sicher kann er. Nur warum sollte er?
>
> <skeptisch>Weil es schneller ist?</skeptisch>
Warum sollte mich das mehr interessieren als der Funktionsaufruf?
>> Aus pragmatischen Gründen würde ich Literale nur in Ausnahmefällen
>> direkt in den Quellcode schreiben.
>
> Davon spricht hier ja auch keiner.
sqrt(4) ist effektiv ein Literal.
>>>>>> /home/rw/work/sentry/tmp/sentry_conf_file.o2(.text+0x5a): the use
>>>>>> of `tempnam' is dangerous, better use `mkstemp'
>>>>
>>>> [...]
>>
>> Using filenames generated by ... can be hazardous.
>>
>> Man könnte sogar den überdramatischen Tonfall beibehalten.
>
> Ich denke, daß diese Funktion häufig falsch verwendet wird, und vor
> allen, daß dabei immer gleich ein riesen Schaden entsteht, wenn man
> es macht. Ich empfinde es als vorteilhaft, eine Umgebung zu
> benutzen, die mich vor solchen sachen warnt.
Sie warnt aber nicht vor dem Problem, sondern gibt völligen Müll aus.
> BTW: Du könnstest Dir einiges an Verrenkungen sparen, würdest Du
> einfach eine andere Funktion als tempnam verwenden.
Leider gibt es die aber nicht, was Du anhand der Verwendung von path
und prefix auch selber hättest sehen können.
Rainer Weikusat <weik...@students.uni-mainz.de> wrote:
> Bodo Thiesen <bot...@gmx.de> writes:
>> Rainer Weikusat <weik...@students.uni-mainz.de> wrote:
>>> Es verkompliziert sich aber gar nichts, im Gegenteil. Der Sender muß
>>> nie Daten konvertieren, der Empfänger nur, falls der Sender nicht sein
>>> natives Datenformat benutzt.
>>
>> Also beim Senden einmal hton() und beim Empfangen einmal ntoh() zu machen
>> ist doch wohl einfacher, als ein unbekannted Datenformat ins native
>> Format zu übersetzen.
> Beim Senden gar nichts zu tun und beim Empfangen ggf die Endianness
> umzustellen erfordert ein Flag im Datensatz und nicht mehr Code, als
> andernfalls auch gebraucht würde.
Doch, es benötigt Code zum Auswerten des Flags. Und ein
bedingter Sprung ist sehr langsam. Ein unbedingtes 'bswap' ist
hingegen ziemlich schnell.
Es kann ja sein, daß man mit "deiner" Variante manchmal spart.
Genauso ist es aber eben möglich, daß man manchmal draufzahlt.
[...]
>>> Darauf wollte ich hinaus. Dh er sollte keine Funktionen ungebeten
>>> inline expandieren und erst recht keine Aufrufe wechselseitig
>>> ersetzen.
>>
>> Dann sag das dem Compiler, und er tut es nicht. Wundere Dich dann aber
>> auch nicht darüber, daß Deine Programme 10 mal langsamer werden.
> Zehnmal langsamer als was?
Als der Code mit Inlining. Gerade gcc bietet ja nun genug
Optionen, dir den Optimizer zurechtzukonfigurieren, wie du ihn
magst. Der Default ist halt "Optimieren auf Geschwindigkeit",
weil das viele Leute so möchten.
>>> 'Auf Geschwindigkeit optimiert' wäre das, wenn der Compiler wegen
>>> fehlendem loop-body erkennen würde, daß er das als
>>>
>>> cnt = 10000;
>>> do { --cnt; } while (cnt);
>>
>> Warum das? Nicht nur, daß das ein Fehler ist, nein, die Schleife ist auch
>> noch sinnfrei.
> Die Schleife war vorher auch schon sinnfrei, aber weil der (in diesem
> Fall leere) Schleifekörper erkennbar nicht von der Zählrichtung
> abhängt, kann man sie umdrehen.
Wenn der Schleifenkörper leer ist, kann man die Schleife auch
komplett rausnehmen. Man ändert damit bestenfalls das
Zeitverhalten des Programmes, aber der Default des Optimizers ist
nun mal "Optimieren auf Geschwindigkeit".
BTW, 'info (gcc)Non-bugs':
# Historically, GCC has not deleted "empty" loops under the
# assumption that the most likely reason you would put one in a
# program is to have a delay, so deleting them will not make real
# programs run any faster.
So ziemlich genau dein Argument (wobei delay-loops m.M.n. nur
in einem System-Kern sinnvoll sind, wo eh andere Spielregeln
gelten. Nutzer können usleep verwenden).
# However, the rationale here is that optimization of a nonempty loop
# cannot produce an empty one, which holds for C but is not always
# the case for C++.
Und das ist das eigentliche Problem. Man kann leere Schleifen
erhalten, ohne sie explizit im Programm stehen zu haben.
Übrigens auch in C, und auch ohne 'optimisation of a nonempty
loop'. Wenn wir schon bei Byteorder waren:
#ifdef __HOST_BIG_ENDIAN__
# define swap_to_host_byteorder(x) ((void)(x))
#else
# define swap_to_host_byteorder(x) (__asm__(......))
#endif
...und woanders dann...
for (i = 0; i < N; ++i)
swap_to_host_byteorder(&array[i]);
Im Fall __HOST_BIG_ENDIAN__ hätten wir dann eine leere Schleife,
die durchaus eliminiert werden kann. Die Alternative wäre,
meinen Nutzercode mit obskuren System-#defines zu verunstalten.
> i = 0;
> do { x[i] = y[i] } while (++i < 10000);
> i = 10000;
> do { --i; x[i] = y[i]; } while (i);
(Das ist übrigens nur dann äquivalent, wenn der Compiler
garantieren kann, daß 'x' und 'y' nicht überlappen.)
>>>> Der Compiler kann sehr wohl "sqrt(4)" einfach durch "2.0" ersetzen,
>>>> eben weil er die Funktion und ihre Effekte kennen darf.
>>>
>>> Sicher kann er. Nur warum sollte er?
>>
>> <skeptisch>Weil es schneller ist?</skeptisch>
> Warum sollte mich das mehr interessieren als der Funktionsaufruf?
Geschwindigkeit interessiert nun mal viele Leute mehr als der
Funktionsaufruf. Wenn du Wert auf den Funktionsaufruf legst,
schalte den Inliner ab. Fertig. Irgendwie sehe ich hier
überhaupt kein Problem.
Stefan
Stellt sich nur die Frage, ob die Auswertung innerhalb oder ausserhalb
der Schleife stattfindet. Es wäre durchaus möglich, den gesamten
I/O-Code zweimal zu übersetzten. Und beim zweiten mal dann
#define htonl(hostlong) hostlong
zu definieren.
Um diese zwei Übersetzungseinheiten dann in einem Programm zu verwenden,
könnte man entweder die exportierten Bezeichner ebenfalls per
Prä-Prozessor umsetzen. Oder zwei verschiedene Shared-Libraries erzeugen.
--
Google ist Gott. Opfere ihr deine Zeit und werde erleuchtet.
Das ist nicht 'meine Variante', sondern OSF RPC. Ohne den Code
gesehen zu haben, weiss ich immerhin, dass RPC-Aufrufe ueblicherweise
mehrer Argumente haben (typisch waeren Strukturen) und weil das
Interface in einer Bibliothek steckt, wird jedes dieser Argumente
einmal aus dem Speicher geladen, konvertiert und wieder
zurueckgespeichert. Is leider nix mit 'ad hoc'-Konversionen, tut mir
leid. Ansonsten brauchst Du nicht mit mir darueber zu diskutieren,
warum ein Herstellerkonsortium mal irgendeinen Standard so und nicht
anders definiert hat, oder warum manche Leute gewisse Dinge in
irgendwelche Buecher geschrieben haben, denn mit beidem habe ich
nichts zu tun und solange Du nicht ein paar Standardwerke ueber
Betriebssystemkernel geschrieben hast, oder sonst irgendetwas
bedeutendes auf diesem Gebiet vollbracht, gehe ich mal davon aus, das
wahrscheinlich Du derjenige bist, der hier dummes Zeug
redet. Ansonsten waere es vielleicht angemessen, diese 'Nein!' 'Doch!'
'Nein!' 'Doch!'-Disgression entweder zu beenden oder in eine dafuer
passende Gruppe zu verlagern.
>>> wollte ich hinaus. Dh er sollte keine Funktionen ungebeten
>>>> inline expandieren und erst recht keine Aufrufe wechselseitig
>>>> ersetzen.
>>>
>>> Dann sag das dem Compiler, und er tut es nicht. Wundere Dich dann aber
>>> auch nicht darüber, daß Deine Programme 10 mal langsamer werden.
>
>> Zehnmal langsamer als was?
>
> Als der Code mit Inlining.
Als *welcher* Code mit inlining? Und woher kommt der Faktor 10? Du
hast schon mal davon gehoert, das es Mengen von Programmen gibt, die
*nicht* CPU-bound sind, ja? Kannst Du das irgendwie belegen, zB 'Linux
mit -O3 uebersetzt laeuft n mal schneller als Linux mit -O2 und
manuellem inlining (bei ... zusaetzlichen Speicherplatzverbrauch).
> Gerade gcc bietet ja nun genug
> Optionen, dir den Optimizer zurechtzukonfigurieren, wie du ihn
> magst. Der Default ist halt "Optimieren auf Geschwindigkeit",
Wie bereits at length ausgefuehrt: Der default ist 'tu irgendwas', und
ob der Code dadurch schneller, langsamer oder bloss wirrer wird, ist
durchaus offen (und hier immer noch OT). Sie beruehrt auch die
konkrete Fragestellung welchen Nutzen man davon haben sollen koennte,
wenn der Compiler hingeschlampten Code 'optimiert' nicht mal am Rande
(Literale gehoeren nicht in den Quelltext, ausser als benannte
Konstanten).
>>>> cnt = 10000;
>>>> do { --cnt; } while (cnt);
>>>
>>> Warum das? Nicht nur, daß das ein Fehler ist, nein, die Schleife ist auch
>>> noch sinnfrei.
>
>> Die Schleife war vorher auch schon sinnfrei, aber weil der (in diesem
>> Fall leere) Schleifekörper erkennbar nicht von der Zählrichtung
>> abhängt, kann man sie umdrehen.
>
> Wenn der Schleifenkörper leer ist, kann man die Schleife auch
> komplett rausnehmen.
Dann hat man sie allerdings nicht 'optimiert' (dh zweckmaessig
uebersetzt), sondern ignoriert (auf der Basis der wackligen Annahme,
das sie versehentlich leer war).
> # However, the rationale here is that optimization of a nonempty loop
> # cannot produce an empty one, which holds for C but is not always
> # the case for C++.
>
> Und das ist das eigentliche Problem. Man kann leere Schleifen
> erhalten, ohne sie explizit im Programm stehen zu haben.
Nein.
> Übrigens auch in C, und auch ohne 'optimisation of a nonempty
> loop'. Wenn wir schon bei Byteorder waren:
> #ifdef __HOST_BIG_ENDIAN__
> # define swap_to_host_byteorder(x) ((void)(x))
> #else
> # define swap_to_host_byteorder(x) (__asm__(......))
> #endif
> ...und woanders dann...
> for (i = 0; i < N; ++i)
> swap_to_host_byteorder(&array[i]);
> Im Fall __HOST_BIG_ENDIAN__ hätten wir dann eine leere Schleife,
> die durchaus eliminiert werden kann. Die Alternative wäre,
... wie immer in C: Prozedurale Abstraktion.
#ifdef whatever
# void swapem(u32 *start, size_t n) { ... }
#else
# define swapem(s, n)
#endif
>>>>> Der Compiler kann sehr wohl "sqrt(4)" einfach durch "2.0" ersetzen,
>>>>> eben weil er die Funktion und ihre Effekte kennen darf.
>>>>
>>>> Sicher kann er. Nur warum sollte er?
>>>
>>> <skeptisch>Weil es schneller ist?</skeptisch>
>
>> Warum sollte mich das mehr interessieren als der Funktionsaufruf?
>
> Geschwindigkeit interessiert nun mal viele Leute mehr als der
> Funktionsaufruf.
Wenn Dich Geschwindigkeit interessiert, verlaesst Du Dich nicht
darauf, das ein eventuell gar nicht vorhandener Optimierer Dir
hinterherraeumt. Dann benutzt Du einen profiler oder sowas und suchst
nach bottleneckst *anstatt* wahllos den Code zu aendern.
Oh ja, bloss dass der Sender eines von n nativen Datenformaten benutzen
kann. Vielleicht mache ich mich ja jetzt zum Doedel (nicht dass Mathe
meine Staerke waere), aber gibt das bei Werten mit 32 Bit nicht 24
Varianten und bei 64 Bit schon 40320?
Siehe auch Jargon File, Eintrag middle-endian - der Glaube es gaebe nur
Big oder Little Endian ist ein ketzerischer Irrglaube.
> [maschinennahe Sprachen/ C]
>
> >> die Größe der Basisintegers ist direkt an die Maschinenwortgröße
> >> gekoppelt
> >
> > Das ist nicht ganz korrekt. Wenn die Wortgroesse zu klein ist kann das
> > so nicht gemacht werden.
>
> Ich meine mich allerdings an 'an int shall have the size that is most
> natural for the machine' (oä) erinnern zu können.
6.2.5.5
... A plain int object has the natural size suggested by the
architecture of the execution environment (large enough to contain any
value in the range INT_MIN to INT_MAX as defined in the header
<limits.h>).
Siehst Du, kein "shall" und obendrein weitere Bedingungen... ;-)
> >> Variablennamen referieren auf Speicherlokationen mit grundsätzlich
> >> typlosem Inhalt etc.
> >
> > Jede Menge Sprachen haben Variablen ohne RTTI, wieso ist das ein
> > besonderes Merkmal von C?
>
> Das hier ist ein besonderes Merkmal von C:
>
> signed char x;
> unsigned short y;
>
> x = -1;
> y = x + 512;
>
> Eine Integer-Variable entspricht einem Container einer bestimmten
> Größe, der eine mehr oder minder willkürlich Untermenge der
> natürlichen Zahlen in Binärdarstellung beinhalten. Falls ich den Wert
> der Variablen benutze, wird er zu int promoted (vereinfach), vulgo:
> Auf die Maschinenwortgröße expandiert (weil mutmaßlich in ein Register
> geladen),
Keineswegs, die Regeln sind komplizierter und koennen sehr wohl zu
Zwischenwerten groesser als die Maschinenwortgroesse fuehren. Nicht jede
Kiste mit einer C-Implementation hat Register mit 32 Bit, geschweige
denn 64 Bit.
> dann wird irgendeine Operation damit durchgeführt und das
> Resultat wird im Falle einer Zuweisung transparent an einen anderen
> Containertyp angepasst. Auch wenn sich dadurch dadurch ggf der Wert
> ändert:
Das ist wohl wahr.
[snip]
> Was an C auch noch dankenswert hervorzuheben ist, ist die faktische
> Abwesenheit von Aufzählungstypen, außer als selbstausgesuchter
> Fiktion.
Ich dachte ich haette "enum" schon mal gesehen. Ich bin nicht sicher ob
das in C99 einen echten Typ definiert.
> > Und wieso hat das was mit maschinennah zu tun,
> > hatten nicht die Lisp-Machines RTTI in Hardware oder zumindest ganz
> > ganz unten in der Software?
>
> Lisp ist auch eine ziemlich typloses Sprache ... :-).
Hehe. Ich mag nicht was die Emacs-Lisp Programmierer da so tun,
Funktionen mit unterschiedlichem Verhalten je nach Typ eines
uebergebenen Parameters sind IMHO pervers...
> >> Er sollte keine Transformationen auf Quelltextebene durchführen (auch
> >> keine verdeckten), außer es ist beweisbar, daß die tatsächlich eine
> >> Verbesserung bewirken und nicht bloß eine Änderung.
> >
> > Also gar keine, da sowas i.A. nicht beweisbar ist und man sowieso
> > erstmal "Verbesserung" exakt definieren muesste (viel Spass).
>
> Darauf wollte ich hinaus. Dh er sollte keine Funktionen ungebeten
> inline expandieren und erst recht keine Aufrufe wechselseitig
> ersetzen.
Warum nicht?
Denk das mal zu Ende. Das heisst im Extremfall dass der Compiler
ueberhaupt keine Aenderungen an dem von Dir geschriebenen Code machen
darf.
Bloederweise ist das seine ganze Existenzberechtigung - er uebersetzt
den geschriebenen Code in eine ganz andere Sprache was er nach Deinen
Anforderungen garnicht duerfte weil das bloss eine Aenderung und keine
beweisbare Verbesserung ist.
[snip]
> > Das ist einfach eine Folge davon dass Compiler i.A. auf Geschwindigkeit
> > optimieren (sollen).
>
> 'Auf Geschwindigkeit optimiert' wäre das, wenn der Compiler wegen
> fehlendem loop-body erkennen würde, daß er das als
>
> cnt = 10000;
> do { --cnt; } while (cnt);
>
> übersetzen könnte (entsprechende Maschinenbefehle vorausgesetzt). Wenn
> ich den Code weglasse, wird er nicht ausgeführt. Jetzt stellt sich
> allerdings die Frage: Warum stand er da? (Antwort: Weil das ein blödes
> Beispiel ist ;-).
Benchmark eben.
> Es ist inconceivable, das 'dead code' gleichzeitig dead und
> performancekritisch ist, dh ich kann hier einfach keinen denkbaren
> Nutzen erkennen.
Reale Beispiele sind nicht so trivial. Siehe direkt unten.
> > Der Compiler kann sehr wohl "sqrt(4)" einfach durch "2.0" ersetzen, eben
> > weil er die Funktion und ihre Effekte kennen darf.
>
> Sicher kann er. Nur warum sollte er?
Weil er kann und der Compiler-Bauer dachte es waere eine gute Idee und
der Standard es erlaubt? Weil ein Programm den Unterschied eben nicht
feststellen kann?
> Aus pragmatischen Gründen würde ich Literale nur in Ausnahmefällen
> direkt in den Quellcode schreiben.
Verstehe ich nicht, dann muesste Dir ja so eine Optimierung sehr recht
sein?
> >> >> /home/rw/work/sentry/tmp/sentry_conf_file.o2: In function `start_sentry_conf_file':
> >> >> /home/rw/work/sentry/tmp/sentry_conf_file.o2(.text+0x5a): the use of
> >> >> `tempnam' is dangerous, better use `mkstemp'
> >>
> >> [...]
> >>
> >> > Was ist denn so falsch an so einer fuer Dich leicht ignorierten
> >> > Warnung?
> >>
> >> Sie ist sachlich falsch.
> >
> > Eine Compiler-Message ist keine wissenschaftliche Aussage,
>
> Using filenames generated by ... can be hazardous.
>
> Man könnte sogar den überdramatischen Tonfall beibehalten.
Das ist natuerlich ganz lustig, bloss wenn ich jemanden effektiv sagen
hoere dass er nie einen Fehler macht oder nie eine unklare/falsche
Aussage macht dann kann ich ein breites Grinsen nicht unterdruecken.
<grin kind="extra-wide"/>
>Bodo Thiesen <bot...@gmx.de> writes:
>> Rainer Weikusat <weik...@students.uni-mainz.de> wrote:
>>> Es verkompliziert sich aber gar nichts, im Gegenteil. Der Sender muß
>>> nie Daten konvertieren, der Empfänger nur, falls der Sender nicht sein
>>> natives Datenformat benutzt.
>>
>> Also beim Senden einmal hton() und beim Empfangen einmal ntoh() zu
>> machen ist doch wohl einfacher, als ein unbekannted Datenformat ins
>> native Format zu übersetzen.
>
> Beim Senden gar nichts zu tun und beim Empfangen ggf die Endianness
> umzustellen erfordert ein Flag im Datensatz und nicht mehr Code, als
> andernfalls auch gebraucht würde. Erzähle bitte den gewesenen
> Mitgliedern der OSF (ua IBM, MIT und HP), das ihre Ingenieure/
> Wissenschaftler alles Idioten sind.
Ich erlebe das gleiche Problem im Moment während der Entwicklung eines
Programms, bei dem ich mit einigen anderen Leuten im Team arbeite. Einer
aus Estland, ein paar Franzosen, mindestens ein Israeli ist auch permanent
"an Bord". Ich stelle mir gerade den Protest vor, wenn ich vorschlage, daß
wir alle in unserer eigenen Sprache senden, und die Transformation nur
beim Empfangen stattzufinden hat.
Nein, wir machen das so: Jeder transformiert in ein festgelegtes Format
(englisch) und jeder transformiert selbst von diesem Austauschformat in
sein natives Format (z.B. Deutsch, Französisch, Hebräisch ...) zurück. Das
funktioniert wunderbar, und ist für alle zusammen und für jeden
einzelnen der geringste Aufwand.
>>> Ich meine mich allerdings an 'an int shall have the size that is most
>>> natural for the machine' (oä) erinnern zu können. Eine
>>> Implementierung, die ein shall-constraint nicht einhält, bewegt sich
>>> mittig in dem was laut C 'undefiniert' ist. Strengenommen ist das eine
>>> Umgebung, die einen Teil von C emuliert, aber kein C.
>>
>> Was ist denn sie "size that is most natural for the machine" bei der
>> ia32 Architektur? 8 Bit (ah, al, ...), 16 Bit (ax, bx, ...) oder 32 Bit
>> (eax, ebx, ...)? Zumindest was die ia32 Architektur angeht, sind alle
>> drei größen gleich "natural for the machine".
>
>Sie sind es nicht. Wortgröße für ia32 sind (Überraschung!) 32 Bit.
Und warum kennt dann die ia32 Architektur auch 8Bit-Befehle? Und warum muß
ich im Real-Mode sogar noch explizit ein Präfix vor den Befehl setzen,
damit daraus auch wirklich ein 32Bit-Befehl wird? Ich denke mal, das war
jetzt ein Schnellschuß von Dir ...
>>> signed char x;
>>> unsigned short y;
>>>
>>> x = -1;
>>> y = x + 512;
>>
>> Entweder y = 511 oder Trap
>
>Es kann hier kein trap geben.
Nein? signed überlauf? Oder erwartest Du etwa doch das richtige Ergebnis?
>>> unsigned short x = 0xffff;
>>> unsigned char y;
>>>
>>> y = x;
>>
>>> y = x => y == x
>>
>>> Diese Eigenschaft ist in C nicht gegeben
>>
>> Nee?
>
>Nein. Gegenbeispiel steht oben.
Wenn ich einen Apfel in einen Mixer tue, bekomme ich den Apfel auch nicht
wieder zurück.
>>> Darauf wollte ich hinaus. Dh er sollte keine Funktionen ungebeten
>>> inline expandieren und erst recht keine Aufrufe wechselseitig
>>> ersetzen.
>>
>> Dann sag das dem Compiler, und er tut es nicht. Wundere Dich dann aber
>> auch nicht darüber, daß Deine Programme 10 mal langsamer werden.
>
>Zehnmal langsamer als was?
Als Programme, die mit -O4 übersetzt werden, dafür aber for (int
i=0;i<10000;++i) ; zu i=10000; wegoptimieren?
>>>> Der Compiler sieht bloss dass da eine Variable hochgezaehlt aber
>>>> ansonsten nie verwendet wird und laesst das weg da es die
>>>> dokumentierten Effekte des Programms nicht veraendert (Ablaufzeit
>>>> gehoert ja nicht dazu).
>>>
>>> Es ist von der Implementierung abhängig, ob sie 'intrinsically' meßbar
>>> ist.
>>
>> Und ich dache, wir hätten uns geeinigt, das Wort Intrinsic nicht zu
>> verwenden ...
>
> Das ist zunächst mal ein englisches Adjektiv mit einer bestimmten
> Bedeutung.
Wir sind hier zunächst mal in *de*.comp.land.c
Über Fachbegriffe reden wir, wenn diese allgemein (d.h. in der Gruppe)
anerkannt sind.
>>> 'Auf Geschwindigkeit optimiert' wäre das, wenn der Compiler wegen
>>> fehlendem loop-body erkennen würde, daß er das als
>>>
>>> cnt = 10000;
>>> do { --cnt; } while (cnt);
>>
>> Warum das? Nicht nur, daß das ein Fehler ist, nein, die Schleife ist
>> auch noch sinnfrei.
>
> Die Schleife war vorher auch schon sinnfrei, aber weil der (in diesem
> Fall leere) Schleifekörper erkennbar nicht von der Zählrichtung
> abhängt, kann man sie umdrehen.
>
> i = 0;
> do { x[i] = y[i] } while (++i < 10000);
>
> i = 10000;
> do { --i; x[i] = y[i]; } while (i);
Nicht wenn cnt hinterher noch benutzt wird. Und wenn es nicht benutzt
wird, hat es komplett weggeworfen zu werden.
>>>> Der Compiler kann sehr wohl "sqrt(4)" einfach durch "2.0" ersetzen,
>>>> eben weil er die Funktion und ihre Effekte kennen darf.
>>>
>>> Sicher kann er. Nur warum sollte er?
>>
>> <skeptisch>Weil es schneller ist?</skeptisch>
>
> Warum sollte mich das mehr interessieren als der Funktionsaufruf?
Wenn Dich irgendwas außer dem Ergebnis interessiert, kannst Du es nicht
mit Mitteln des Standards realisieren, und dann belästige doch bitte
nicht diese Gruppe mit derartigen Versuchen.
>>> Aus pragmatischen Gründen würde ich Literale nur in Ausnahmefällen
>>> direkt in den Quellcode schreiben.
>>
>> Davon spricht hier ja auch keiner.
>
> sqrt(4) ist effektiv ein Literal.
Dann mach ein #define WURZEL_VON_4 sqrt(4) und schreib statt i=sqrt(4);
i=WURZEL_VON_4;
>>>>>>> /home/rw/work/sentry/tmp/sentry_conf_file.o2(.text+0x5a): the use
>>>>>>> of `tempnam' is dangerous, better use `mkstemp'
>>>>>
>>>>> [...]
>>>
>>> Using filenames generated by ... can be hazardous.
>>>
>>> Man könnte sogar den überdramatischen Tonfall beibehalten.
>>
>> Ich denke, daß diese Funktion häufig falsch verwendet wird, und vor
>> allen, daß dabei immer gleich ein riesen Schaden entsteht, wenn man
>> es macht. Ich empfinde es als vorteilhaft, eine Umgebung zu
>> benutzen, die mich vor solchen sachen warnt.
>
> Sie warnt aber nicht vor dem Problem, sondern gibt völligen Müll aus.
Wenn man das Problem nicht kennt, sollte man in dem Moment, in dem man die
Warnung liest, dieses in Erfahrung bringen (ein man tempnam reicht da
schon).
>> BTW: Du könnstest Dir einiges an Verrenkungen sparen, würdest Du
>> einfach eine andere Funktion als tempnam verwenden.
>
> Leider gibt es die aber nicht, was Du anhand der Verwendung von path
> und prefix auch selber hättest sehen können.
Nun, wenn es Dir wirklich wichtig ist, wo Deine Temp-Dateien landen, und
wie sie heißen ...
(Normalerweise empfinde ich /tmp als ein ausgesprochen guten Platz für
solche Zwecke.)
> Rainer Weikusat <weik...@students.uni-mainz.de> wrote:
>
>> Bodo Thiesen <bot...@gmx.de> writes:
>>
>>> Rainer Weikusat <weik...@students.uni-mainz.de> wrote:
>>>
>>>> signed char x;
>>>> unsigned short y;
>>>>
>>>> x = -1;
>>>> y = x + 512;
>>>
>>> Entweder y = 511 oder Trap
>>
>> Es kann hier kein trap geben.
>
> Nein? signed überlauf? Oder erwartest Du etwa doch das richtige Ergebnis?
Es kann hier definitiv keine Trap geben!
1) x ist signed char und kann den Wert -1 problemlos darstellen.
2) Vor der Rechnung x + 512 wird auf Grund der integer promotions der
Wert von x nach int konvertiert, was bei -1 auch kein Problem
darstellt.
3) -1 + 512 ergibt 511. Auch dieser Wert ist im gültigen Wertebereich
für int.
4) Bei der Zuweisung nach y wird dieser Wert nach unsigned short
konvertiert. Auch hier kein Problem.
Kein "signed überlauf", keine Trap, keine sonstige Exception. Alles im
grünen Bereich.
Gruß. Claus
> Rainer Weikusat <weik...@students.uni-mainz.de> writes:
>
>> Was an C auch noch dankenswert hervorzuheben ist, ist die faktische
>> Abwesenheit von Aufzählungstypen, außer als selbstausgesuchter
>> Fiktion.
>
> Ich dachte ich haette "enum" schon mal gesehen. Ich bin nicht sicher ob
> das in C99 einen echten Typ definiert.
enum deklariert int-Konstanten (§6.7.2.2p3).
Aber was ist ein "Aufzählungstyp"?
Gruß. Claus
Rainer Weikusat <weik...@students.uni-mainz.de> wrote:
> Stefan Reuther <sr...@inf.tu-dresden.de> writes:
>> Rainer Weikusat <weik...@students.uni-mainz.de> wrote:
>>> Beim Senden gar nichts zu tun und beim Empfangen ggf die Endianness
>>> umzustellen erfordert ein Flag im Datensatz und nicht mehr Code, als
>>> andernfalls auch gebraucht würde.
>>
>> Doch, es benötigt Code zum Auswerten des Flags. Und ein
>> bedingter Sprung ist sehr langsam. Ein unbedingtes 'bswap' ist
>> hingegen ziemlich schnell.
>>
>> Es kann ja sein, daß man mit "deiner" Variante manchmal spart.
[...]
> Ansonsten brauchst Du nicht mit mir darueber zu diskutieren,
> warum ein Herstellerkonsortium mal irgendeinen Standard so und nicht
> anders definiert hat,
Hab ich auch nicht vor. Trotz deines Rants existiert NFS und
funktioniert, und bis her hat es noch niemand für saugstark
genug gehalten, um es ernsthaft zu ersetzen.
> und solange Du nicht ein paar Standardwerke ueber
> Betriebssystemkernel geschrieben hast, oder sonst irgendetwas
> bedeutendes auf diesem Gebiet vollbracht, gehe ich mal davon
> aus, das wahrscheinlich Du derjenige bist, der hier dummes
> Zeug redet.
Dann bitte ich um Referenzen zu den Standardwerken und
Betriebssystemkerneln von Rainer Weikusat.
Fakt ist, daß ich hier auch ein paar Programme habe - auch wenn
es sich dabei um ein Spiel-System handelt - die ebenfalls alles
auf little-endian umcodieren, weil der Erfinder des Spieles zu
faul war, ein "vernünftiges Protokoll" zu entwerfen. Trotz
Umcodierung sind meine Programme Größenordnungen schneller, weil
die I/O nun mal nicht alles ist.
>>>> wollte ich hinaus. Dh er sollte keine Funktionen ungebeten
>>>>> inline expandieren und erst recht keine Aufrufe wechselseitig
>>>>> ersetzen.
>>>>
>>>> Dann sag das dem Compiler, und er tut es nicht. Wundere Dich dann aber
>>>> auch nicht darüber, daß Deine Programme 10 mal langsamer werden.
>>
>>> Zehnmal langsamer als was?
>>
>> Als der Code mit Inlining.
> Als *welcher* Code mit inlining? Und woher kommt der Faktor 10? Du
> hast schon mal davon gehoert, das es Mengen von Programmen gibt, die
> *nicht* CPU-bound sind, ja?
Ja, habe ich.
Ich finde es aber praktisch, wenn ich zum Beispiel abstrakte
Datentypen oder (in C++) Klassen mit Accessor-Funktionen ('int
getFoo() const { return foo; }') verwenden kann, deren Overhead
durch -O2 auf Null gedrückt wird. Ja, ich habe nachgesehen.
>> Gerade gcc bietet ja nun genug
>> Optionen, dir den Optimizer zurechtzukonfigurieren, wie du ihn
>> magst. Der Default ist halt "Optimieren auf Geschwindigkeit",
> Wie bereits at length ausgefuehrt: Der default ist 'tu irgendwas', und
> ob der Code dadurch schneller, langsamer oder bloss wirrer wird, ist
> durchaus offen (und hier immer noch OT).
Andere mögen das nicht so schwarz sehen, auch wenn es
prinzipiell wahr ist. Dennoch wird ein übliches Programm mit -O2
schneller. Merke: "übliches" != "jedes". Du darfst aber gerne
einen Beitrag leisten, Optimierer perfekter zu machen.
>>>>> cnt = 10000;
>>>>> do { --cnt; } while (cnt);
>>>>
>>>> Warum das? Nicht nur, daß das ein Fehler ist, nein, die Schleife ist auch
>>>> noch sinnfrei.
>>
>>> Die Schleife war vorher auch schon sinnfrei, aber weil der (in diesem
>>> Fall leere) Schleifekörper erkennbar nicht von der Zählrichtung
>>> abhängt, kann man sie umdrehen.
>>
>> Wenn der Schleifenkörper leer ist, kann man die Schleife auch
>> komplett rausnehmen.
> Dann hat man sie allerdings nicht 'optimiert' (dh zweckmaessig
> uebersetzt), sondern ignoriert (auf der Basis der wackligen Annahme,
> das sie versehentlich leer war).
Dann definiere endlich mal 'optimieren'. Für den Compiler (und
mich) ist das erstmal: 'wird schneller bei nicht übermäßig hohen
Extrakosten'.
>> # However, the rationale here is that optimization of a nonempty loop
>> # cannot produce an empty one, which holds for C but is not always
>> # the case for C++.
>>
>> Und das ist das eigentliche Problem. Man kann leere Schleifen
>> erhalten, ohne sie explizit im Programm stehen zu haben.
> Nein.
Wenn du mein Beispiel nicht lesen willst, kann ich aber auch
nicht helfen.
>> Übrigens auch in C, und auch ohne 'optimisation of a nonempty
>> loop'. Wenn wir schon bei Byteorder waren:
>> #ifdef __HOST_BIG_ENDIAN__
>> # define swap_to_host_byteorder(x) ((void)(x))
>> #else
>> # define swap_to_host_byteorder(x) (__asm__(......))
>> #endif
>> ...und woanders dann...
>> for (i = 0; i < N; ++i)
>> swap_to_host_byteorder(&array[i]);
>> Im Fall __HOST_BIG_ENDIAN__ hätten wir dann eine leere Schleife,
>> die durchaus eliminiert werden kann. Die Alternative wäre,
> ... wie immer in C: Prozedurale Abstraktion.
> #ifdef whatever
> # void swapem(u32 *start, size_t n) { ... }
> #else
> # define swapem(s, n)
> #endif
Welches #define würde ich nehmen, wenn da im Original
for (i = 0; i < N; ++i)
array[i] = htonl(array[i]);
stünde? Sinn von 'htonl' ist gerade, daß ich *keine*
configure-Skripte schreiben muß, um die Endianness selber
rauszufinden.
>>>>>> Der Compiler kann sehr wohl "sqrt(4)" einfach durch "2.0" ersetzen,
>>>>>> eben weil er die Funktion und ihre Effekte kennen darf.
>>>>>
>>>>> Sicher kann er. Nur warum sollte er?
>>>>
>>>> <skeptisch>Weil es schneller ist?</skeptisch>
>>
>>> Warum sollte mich das mehr interessieren als der Funktionsaufruf?
>>
>> Geschwindigkeit interessiert nun mal viele Leute mehr als der
>> Funktionsaufruf.
> Wenn Dich Geschwindigkeit interessiert, verlaesst Du Dich nicht
> darauf, das ein eventuell gar nicht vorhandener Optimierer Dir
> hinterherraeumt.
Doch. Jeder C-Programmierer verläßt sich darauf, daß der
Compiler constant-folding macht. Wir leben am Anfang des 21.
Jahrhunderts, da darf ich auch einfaches inlining erwarten.
Meine Programme haben primär für Menschen lesbar zu sein, denn
Menschen haben ein kleineres Gedächtnis als Compiler. Deswegen
gibt's bei mir auch meistens semi-brauchbare Kommentare.
Stefan
Das tut er ja sowieso. Irgendwer muß also konvertieren. Aber nicht
beide und nicht unbedingt.
[...]
>> Eine Integer-Variable entspricht einem Container einer bestimmten
>> Größe, der eine mehr oder minder willkürlich Untermenge der
>> natürlichen Zahlen in Binärdarstellung beinhalten. Falls ich den Wert
>> der Variablen benutze, wird er zu int promoted (vereinfach), vulgo:
>> Auf die Maschinenwortgröße expandiert (weil mutmaßlich in ein Register
>> geladen),
>
> Keineswegs, die Regeln sind komplizierter und koennen sehr wohl zu
> Zwischenwerten groesser als die Maschinenwortgroesse fuehren.
Deswegen »vereinfach[t]«. Ich vermute das als Ursprung.
>> Was an C auch noch dankenswert hervorzuheben ist, ist die faktische
>> Abwesenheit von Aufzählungstypen, außer als selbstausgesuchter
>> Fiktion.
>
> Ich dachte ich haette "enum" schon mal gesehen. Ich bin nicht sicher ob
> das in C99 einen echten Typ definiert.
Es tut. Lediglich darf man es für alle praktischen Zwecke ignorieren.
[...]
>> Aus pragmatischen Gründen würde ich Literale nur in Ausnahmefällen
>> direkt in den Quellcode schreiben.
>
> Verstehe ich nicht, dann muesste Dir ja so eine Optimierung sehr recht
> sein?
Nicht im Mindesten. Morgen kommt jemand auf den Gedanken, daß die
Quadratwurzel von 16 doch auch eine schöne Zahl ist und dann muß das
an achtzig Stellen im Quellcode von Hand angepaßt werden und bis der
Optimizer diese Zeit wieder hereingeholt hat, dürfte einiges an
Rechenzeit den Bach heruntergegangen sein.
>> >> Sie ist sachlich falsch.
>> >
>> > Eine Compiler-Message ist keine wissenschaftliche Aussage,
>>
>> Using filenames generated by ... can be hazardous.
>>
>> Man könnte sogar den überdramatischen Tonfall beibehalten.
>
> Das ist natuerlich ganz lustig, bloss wenn ich jemanden effektiv sagen
> hoere dass er nie einen Fehler macht oder nie eine unklare/falsche
> Aussage macht dann kann ich ein breites Grinsen nicht unterdruecken.
Mittlerweile verursacht die rethorische Volte weg vom Thema und hin zu
den (unterstellten) Charakterdefiziten von Diskussionsteilnehmern bei
mir leider nur noch ein ausgeleiertes Gähnen. Nehmen wir mal an ein
böser Kinderschänder behauptet, zwei und zwei addiert ergäbe
vier. Welche Rückschlüsse läßt sein Vorleben auf den Wahrheitsgehalt
der Aussage zu?
>enum deklariert int-Konstanten (§6.7.2.2p3).
>
>Aber was ist ein "Aufzählungstyp"?
<news:bhvr2s$3lkm0$1...@ID-175126.news.uni-berlin.de>, Body, Zeile 11 ff.
z.B.
Nein, das gibt es so in C nicht, aber Du hast danach gefragt.
Vinzent.
Dann unterlasse es bitte in Zukunft.
> Bodo Thiesen schrieb:
>
>> Rainer Weikusat <weik...@students.uni-mainz.de> wrote:
>>
>>> Bodo Thiesen <bot...@gmx.de> writes:
>>>
>>>> Rainer Weikusat <weik...@students.uni-mainz.de> wrote:
>>>>
>>>>> signed char x;
>>>>> unsigned short y;
>>>>>
>>>>> x = -1;
>>>>> y = x + 512;
>>>>
>>>> Entweder y = 511 oder Trap
>>>
>>> Es kann hier kein trap geben.
>>
>> Nein? signed überlauf? Oder erwartest Du etwa doch das richtige
>> Ergebnis?
>
> Es kann hier definitiv keine Trap geben!
Richtig (ist mir von Anfang an klar gewesen). Um so mehr wundert es mich,
daß sich Rainer genau darüber wundert/aufregt.
> Mathias Grimmberger <mg...@zaphod.sax.de> writes:
>> Rainer Weikusat <weik...@students.uni-mainz.de> writes:
>>> Es verkompliziert sich aber gar nichts, im Gegenteil. Der Sender muß
>>> nie Daten konvertieren, der Empfänger nur, falls der Sender nicht sein
>>> natives Datenformat benutzt.
>>
>> Oh ja, bloss dass der Sender eines von n nativen Datenformaten benutzen
>> kann.
>
> Das tut er ja sowieso. Irgendwer muß also konvertieren. Aber nicht
> beide und nicht unbedingt.
Bei 16 Bit Zahlen gibt es genau 65536! (Faktulät) Datenformate. Von
32 oder gar 64 Bit Zahlen will ich garnicht erst sprechen. Der Overhead um
dies auszuhandeln (von einem Algorithmus will ich hier auch nicht
sprechen) ist alleine schon mehr, als einfach einmal beim Senden und
einmal beim Empfangen in bzw. von Network Byte Order ins Native Format zu
übersetzen.
>>> Aus pragmatischen Gründen würde ich Literale nur in Ausnahmefällen
>>> direkt in den Quellcode schreiben.
>>
>> Verstehe ich nicht, dann muesste Dir ja so eine Optimierung sehr recht
>> sein?
>
> Nicht im Mindesten. Morgen kommt jemand auf den Gedanken, daß die
> Quadratwurzel von 16 doch auch eine schöne Zahl ist und dann muß das
> an achtzig Stellen im Quellcode von Hand angepaßt werden und bis der
> Optimizer diese Zeit wieder hereingeholt hat, dürfte einiges an
> Rechenzeit den Bach heruntergegangen sein.
Jetzt verstehe ich Dich nicht. Wo siehst Du denn bei einer Änderung von
#define MAGIC sqrt(4) zu #define MAGIC sqrt(16) achtzig Änderungen? Ich
sehe da genau eine, und das kommt ja genau daher, daß man eben KEINE
Literale in die Quellen schreibt. Und der Optimizer hat dann bitte beim
Übersetzen sqrt(4) durch 2 zu ersetzen. Dafür muß ich als
Programmierknecht aber nur exakt eine Zeile ändern.
Jedes Bit von 2^0 bis 2^15 kann eine der 16 zur Verfügung stehenden
Positionen einnehmen, das macht dann 16! mögliche Datenformate.
> Von 32 oder gar 64 Bit Zahlen will ich garnicht erst sprechen.
Gut, dann würdest du wahrscheinlich noch mehr Unsinn erzählen.