[C] printf notwendig? / zählen zur 16.777.216

shutdown

Erfahrenes Mitglied
Hi!

Heute möchte ich euch mal meine zwei großen C-Mysterien präsentieren, die mir bisher bei meiner Programmiertätigkeit aufgetreten sind und bin gespannt, ob irgendjemand eine einleuchtende Lösung parat hat.

Mysterium Nr.1: printf bei Dateioperationen
Wenn ich mit Dateien als Input/Output für meine C-Routinen arbeite, muss ich immer gleichzeitig eine Ausgabe auf der Konsole erzeugen. Tue ich das nicht, bricht er mir nach 2 Sekunden ab. Dieses Problem tritt bei mir sowohl unter Linux als auch unter Windows auf.
Es kann doch nicht sein, dass durch das Weglassen der Konsolen-Ausgabe, das Programm so schnell wird, dass die Datei-Operationen nicht mehr hinterherkommen, oder?

Mysterium Nr. 2: Zählen bis zur 16.777.216
Wenn ich in einer for-Schleife eine float-Variable hochzähle, dann komme ich genau bis zur 16.777.216 und dann hängt er sich in eine Endlosschleife. Float ist aber zu wesentlich größeren Zahlenbereichen fähig als nur bis 10^8.
Lasse ich die for-Schleife erst bei 16.777.217 einsetzen, zählt er völlig normal weiter.
Dieses Problem tritt wiederum unter Linux genauso wie unter Windows auf.
Ich weiß, dass die Zahl 16.777.216 unter Linux problembehaftet ist ( = 2^24), allerdings geht es meines Wissens dabei um Dinge, wie maximale Dateigrößen (die außerdem schon gar nicht mehr aktuell sind)


Also ich bin gespannt was ihr so meint! :)

cu shutdown
 
Zuletzt bearbeitet:
zu 1 und 2) Zeig einen Code-Schnipsel, sonst kann man kaum etwas Sinnvolles sagen.

Generell würde ich sagen, da ja irgendwie alle anderen keine Probleme damit haben, dass etwas an dem Code oder evtl. den Projekteinstellungen Probleme macht, deshalb bitte Ausschnitte bzw. ganze Schnitte. :)
 
Okay dann schreib ich halt mal schnell ein kleines Beispiel Programm :p

Eigentlich ist oben alles genau beschrieben, aber okay:

zu 1:

Code:
char container[250];

FILE *in, *out;

in = fopen("datei.txt", "r+");

while(fgets(in, 200, container))  // da ich mir das grad ausdenke, bin ich mir bei der 
{                                            // der Parameter von fgets grad nicht sicher
       printf("DIESES PRINTF NOTWENDIG?");
       VERARBEITUNG DER DATEIEN
}

fclose(in);

out = fopen("datei2.txt", "a+");

for(i=0; i<=Inhalt_in_speicher_array; i++)
        fprintf(out, "%s\n", speicher_array[i]);

fclose(out);

Und jetzt das unglaubliche Beispiel für eine for-Schleife

Code:
float i;

for(i=16777210; i<=16777220; i++)
        printf("%f\n", i);
Ein Wahnsinns-Beispiel oder? :)

Ich glaub zwar net, dass diese genialen Beispiele jetzt irgendetwas klarer gemacht haben, als es vorher schon war, aber ich lass mich gerne überraschen ;-)

shutdown
 
Doch, evtl. schon:

bei Beispiel 2, schreib in der For-Schleife statt 16777220 16777220.0f. Sonst wird da ein int als die Konstante genommen, und dann in ein float umgewandelt. Ich vermute, dass du da auf eine int-Grenze stösst (obwohl 24bit eigentlich nie die Grenze sein kann, früher 15bit und zur Zeit 31 bit) und dadurch der Endwert kleiner wird als der Anfangswert, also gibt das eine schöne Fast-Endlosschleife.

zu 1: Was heisst denn "bricht ab" ? Gibt's einen Absturz oder ist das Programm nur so schnell fertig? 200 Bytes sind Killefitt für PCs ab XT. Das merkst du gar nicht, wie schnell das läuft.

Zusätzlich: Stell mal den Warning-Level hoch (falls es die Einstellung bei deinem Compiler gibt), bei MSVC mind. 3. Dann müsste der Compiler bei der int-zu-float-Zuweisung eigentlich Rummeckern.
 
Zuletzt bearbeitet:
okay sorry, hätte ich vielleicht anders schreiben sollen:

Ich habe nicht in der for-Schleife die exakten Werte drinstehen.

Ich lese beide Werte vorher ein:

scanf("%f", von);
scanf("%f", bis);

for(i=von; i<=bis; i++);


und was das "bricht ab" angeht:

Er hört ganz einfach auf! (unter Linux bedeutet das z.B., dass mir mein Standard-Prompt wieder angezeigt wird und ich wieder normal Befehle wie ls eingeben kann)

Und dass er einfach ganz Schnell fertig ist, kann aus folgenden Gründen nicht sein:
1) Ich durchsuche teilweise Zahlenbereiche, die mehrere Millionen Schleifendurchläufe benötigen.
2) Wenn er fertig wäre, würde in der Ausgabe-Datei was stehen

Außerdem kann ich da auf keine int-Grenze stoßen, da ich die 16777216 einer float-Variablen (i) zuweise. (Nebenbei, für int ist irgendwo bei 34000 Sense)

shutdown
 
moin


@Endurion
Hab das mit der Schleife grad mal getestet und das .0f bringt auch nichts, auch wenn was "unsichtbares" hinterm Komma stehen würde, ist man ja trotzdem durch das < (kleriner als) abgesichert.

@shutdown
Eigentlich ist oben alles genau beschrieben, aber okay:
Ein Codeschnippsel hilft imer mehr als eine Beschreibung, da du wenn du deine Fehler nicht iehst sie auch nicht beschreiben kannst.

Kann dein "bricht ab" vielleicht auch einfach sein das er fertig ist?

Werde jetzt selber nochmal ein bscihen Probieren.


mfg
umbrasaxum
 
Nope

er ist sicher nicht fertig :)

Und dass er einfach ganz Schnell fertig ist, kann aus folgenden Gründen nicht sein:
1) Ich durchsuche teilweise Zahlenbereiche, die mehrere Millionen Schleifendurchläufe benötigen.
2) Wenn er fertig wäre, würde in der Ausgabe-Datei was stehen

Wenn ich dem Ding sage, es soll eine for-Schleife 4.000.000 mal ausführen, dann muss er dat machen und kann nicht nach 2 Sekunden schon fertig sein :)

Mal zum Vergleich:
Wenn ich das printf drinlasse, dann benötigt er für 1.000.000 etwa 4 Minuten (bin ich aber nicht mehr ganz sicher)

shutdown
 
moin


scanf("%f", von);
scanf("%f", bis);

ist falsch!

Es muss
scanf("%f", &von);
scanf("%f", &bis);

heissen.

Außer natürlich dein von und bis sind Pointer, aber da du den Teil einfach weggelassen hast kann ich das ja nciht wissen.


mfg
umbrasaxum
 
Höhö, Nachtrag zu 1):

Habs jetzt mal selber ausprobiert, also mit Int-Grenze hat es nix zu tun, aber mit float-Präzision: Floats schaffen zwar Riesen-Zahlen, aber nur bis 6 Stellen Genauigkeit. Und genau da läufst du drauf. Bei float 16777216.0f plus 1 kommt wieder 16777216.0f raus. Es geht, wenn du float in double umänderst bzw. einen anderen, höher aufgelösten Typ von Real-Zahlen.

Zu 2 fällt mir noch ein: Evtl. ist das tatsächlich ein Absturz, vielleicht über ein Array drüberraus geschrieben? Kannst du da nicht einfach mal mit nem Debugger drüber?


Noch ein Nachtrag: ints bis 32767 gibt es mit 16-bit-Umgebungen, arbeitest du auf so einer? Das wäre wichtig zu wissen. Bei 32-bit-Umgebungen gehen die bis 2147483647 (und negativ).
 
Zuletzt bearbeitet:
moin


Noch was zu dem "mit printf langsamer".
Ja mit printf dauert es sehr viel länger, da auch sehr viel mehr gemacht werden muss!
In den Speicher Schreiben, ausgaben, leeren, wieder einlesen......

Aber ich kann mir nciht vorstellen das die Daten ohne printf zuschnell gelesen werden, da fgets sich die Daten ja selber holt und somit die geschwindigkeit selber vorgibt.
Man kann auch sagen das dein Programm solange warten muss bis fgets die nötigen Daten erhalten hat.



mfg
umbrasaxum
 

Neue Beiträge

Zurück