C++Talk.NET Forum Index C++Talk.NET
C++ language newsgroups
 
Archives   FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

printf()
Goto page Previous  1, 2, 3, 4  Next
 
Post new topic   Reply to topic    C++Talk.NET Forum Index -> C++ (German)
View previous topic :: View next topic  
Author Message
Jirka Klaue
Guest





PostPosted: Thu Apr 19, 2007 12:35 am    Post subject: Re: printf() Reply with quote



Stefan Reuther:
Quote:
Jirka Klaue:
Björn Hendriks:

Es gibt jedoch weder für den Compiler zur
Übersetzungszeit noch für die Funktion printf zur Laufzeit die
Möglichkeit zu prüfen, ob tatsächlich die erwarteten Parameter
übergeben wurden.

Ich hoffe, Dir ist klar, daß der Compiler selbstverständlich die
Möglichkeit hat, die Typen zu prüfen und das i.A. auch tut.

Ein Compiler muss 'printf("%d", 2.0)' zumindest übersetzen. Warnungen
bezüglich nichtpassender Typen sind mir nur vom gcc geläufig, und auch
da nur für hinreichend konstante Formatstrings.

Das beweist doch schon, daß es dem Compiler nicht unmöglich ist, den
Formatstring und die Argumente zu prüfen. Davon abgesehen, macht der
Intel-Compiler das auch.

Jirka
Back to top
Björn Hendriks
Guest





PostPosted: Thu Apr 19, 2007 3:16 am    Post subject: Re: printf() Reply with quote



Dirk Clemens wrote:

Quote:
Björn Hendriks wrote:
Sebastian Bormann wrote:

Meiner Ansicht nach liegt der Hauptvorteil von cout in der Typsicherheit.

Und ich dachte der Hauptunterschied wäre, dass printf() eine Funktion
und cout eine Variable von Typ std::ostream ist. Außerdem exisitert
cout nur unter C++, printf() dagegen unter C und C++.

Ob man mit Funktionen oder Objekten arbeitet ist implementationstechnisch
natürlich ein Unterschied, aber für sich noch kein Vor- oder Nachteil.

Quote:
Es gibt jedoch weder
für den Compiler zur Übersetzungszeit noch für die Funktion printf zur
Laufzeit die Möglichkeit zu prüfen, ob tatsächlich die erwarteten
Parameter übergeben wurden.

Und wieso warnt mich dann mein Compiler, wenn ich nicht passende
Parameter übergebe?

OK, ich korrigiere: Der Compiler hat in bestimmten Fällen die Möglichkeit,
zu warnen, wenn Formatstring und Parameter nicht zusammenpassen. Der
Standard zwingt ihn jedoch nicht dazu und da es sich um gültigen
definierten Code handelt, muss der Compiler ihn übersetzen, egal was dabei
herauskommt. Und wenn man weiß, wie ein Stackframe aufgebaut ist und wie
die Parameterübergabe auf dem Stack abläuft, kann man sich ungefähr
vorstellen, wie wichtig vollständige Funktionsprototypen sind.

Außerdem wird es der Compiler schwer haben, den Formatstring zu prüfen, wenn
er erst zur Laufzeit gebildet oder gar aus einer Datei gelesen wird.

Quote:
Beispiel mit 32 bit-Integern:

printf("Zahl %d, Buchstabe %c\n", 'x', 3Cool;

Hier wird printf das 'x' und die ersten drei Bytes des Integers 38 als
Integerzahl interpretieren und das letzte Byte der 38 als Buchstaben, du
erhältst also etwas völlig anderes als erwartet, ohne dass du irgendwie
gewarnt würdest, denn printf ist nicht typsicher.

Für einen erfahrenden C-Programmierer ist die Ausgabe sofort und
schnell nachzuvollziehen und keinesfalls unerwartet.

Wenn man sich lange mit printf auseinandergesetzt hat, kennt man natürlich
dessen Tücken und kann damit umgehen. Das gilt aber für alle anderen Dinge
auch, daher sollten wir uns hier IMHO mehr auf die konkreten Vor- und
Nachteile von printf und cout konzentrieren.

Quote:
Ich würde eher sagen: print() und cout sind 2 verschiedene Philosophien,
von denen *ich* auch unter C++ die printf()-Varianten klar vorziehe,
weil ich sie für viel einfacher und übersichtlicher halte.

Das ist eine Frage der Übung. Als ich vor 20 Jahren mit C angefangen hatte,
gab es nichts anderes und ich habe es aus Gewohnheit zunächst
weiterbenutzt, als ich mit C++ angefangen hatte. Inzwischen habe ich mich
so sehr an cout gewöhnt, dass ich printf gar nicht mehr benutze.

Die Übersicht über die gesamte Ausgabezeile ist in der Tat ein Vorteil von
printff, den ich vermisse. Bei mehreren Ausgabezeilen kann man leichter
sehen, ob sie richtig untereinander passen. Außerdem bedeutet das
Formatieren mit Manipulatoren mehr Tipparbeit.

Was mir bei cout eindeutig besser gefällt ist, abgesehen von der
Typsicherheit, dass die Variablen an der Stelle stehen, an der sie auch im
Ausgabestrom erscheinen und ich sie nicht im Kopf an die Stellen der
Platzhalter setzen muss, was ab einer gewissen Anzahl nervig sein kann.

So long

Björn
Back to top
Florian Kesseler
Guest





PostPosted: Thu Apr 19, 2007 3:30 am    Post subject: Re: printf() Reply with quote



Christoph Bartoschek schrieb:
Quote:
Sebastian Bormann wrote:

Kann mir jmd bitte den Unterschied zwischen printf() und cout
erklären.

printf hat auch den Vorteil, dass man einfach die Stellen hinter dem Komma
bei Gleitkommazahlen bestimmen kann.

Christoph
Kannst du bei Streams auch. Nur nicht ganz so kurz...
Back to top
Andreas Huennebeck
Guest





PostPosted: Thu Apr 19, 2007 12:21 pm    Post subject: Re: printf() Reply with quote

Stefan Reuther wrote:

Quote:
Historische Implementationen von iostream waren gerne mal langsamer als
stdio, einfach deswegen, weil sie im Hintergrund stdio aufgerufen haben
und daher prinzipbedingt nicht schneller sein konnten. Man kann das auch
anders abbilden (IIRC ist bei einer Version der GNU-Library FILE* ein
streambuf, oder sowas in der Art). Das interessiert mich aber momentan
eher weniger: wenn Performance wirklich ein Problem ist, gehe ich gleich
auf Betriebssysteminterfaces wie open/read/write/close. Wenn ich aber
die Wahl zwischen printf() und cout habe, ist Performance i.A. eh kein
Problem.

Ich habe mit dem (damals aktuellen) gcc von 2005 festgestellt, daß
eine Konstruktion mit ostringstream um etwa Faktor 150 langsamer
war als eine mit sprintf; der Code sah im Prinzip etwa so aus:

double data[1000]; // enthält die auszugebenden Daten

#if USE_STREAM
std::string output;
for (int i = 0;i < 1000; ++i)
{
char buf[128];
snprintf(buf, 128, "%f ", data[i]);
buf[127] = '\0';
output += buf;
}
#else
std::ostringstream oss;
for (int i = 0;i < 1000; ++i)
{
oss << data[i] << " ";
}
std::string output = oss.str();
#endif

Ob das heute noch so ist, weiß ich nicht. Obiger Code füttert ein per popen()
angeschlossenes gnuplot mit Plotdaten, und mit USE_STREAM war die
Wiederholrate des Plotdisplays deutlich langsamer.

Tschau
Andreas
--
Andreas Hünnebeck | email: acmh (AT) gmx (DOT) de
----- privat ---- | www : http://www.huennebeck-online.de
Fax/Anrufbeantworter: 0721/151-284301
GPG-Key: http://www.huennebeck-online.de/public_keys/andreas.asc
PGP-Key: http://www.huennebeck-online.de/public_keys/pgp_andreas.asc
Back to top
James Kanze
Guest





PostPosted: Thu Apr 19, 2007 3:00 pm    Post subject: Re: printf() Reply with quote

On Apr 17, 7:49 pm, Jirka Klaue <k...@dresearch.de> wrote:
Quote:
Björn Hendriks:

printf ist eine globale Funktion, die als ersten Parameter einen Zeiger auf
einen Formatstring erwartet. Alle weiteren Parameter können beliebig sein,
denn es handelt sich um eine variable Argumentliste. Welche Parameter
printf im Einzelnen braucht, steht im Formatstring. Es gibt jedoch weder
für den Compiler zur Übersetzungszeit noch für die Funktion printf zur
Laufzeit die Möglichkeit zu prüfen, ob tatsächlich die erwarteten Parameter
übergeben wurden.

Ich hoffe, Dir ist klar, daß der Compiler selbstverständlich die
Möglichkeit hat, die Typen zu prüfen und das i.A. auch tut.

Bei printf in keinem Fall. Wie kann er, wenn die erst zur
Laufzeit bekannt sind?

--
James Kanze (GABI Software) email:james.kanze (AT) gmail (DOT) com
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
Back to top
James Kanze
Guest





PostPosted: Thu Apr 19, 2007 3:02 pm    Post subject: Re: printf() Reply with quote

On Apr 18, 7:22 pm, Stefan Reuther <stefan.n...@arcor.de> wrote:
Quote:
Jirka Klaue wrote:
Björn Hendriks:
printf ist eine globale Funktion, die als ersten Parameter einen
Zeiger auf einen Formatstring erwartet. Alle weiteren Parameter
können beliebig sein, denn es handelt sich um eine variable
Argumentliste. Welche Parameter printf im Einzelnen braucht, steht
im Formatstring. Es gibt jedoch weder für den Compiler zur
Übersetzungszeit noch für die Funktion printf zur Laufzeit die
Möglichkeit zu prüfen, ob tatsächlich die erwarteten Parameter
übergeben wurden.

Ich hoffe, Dir ist klar, daß der Compiler selbstverständlich die
Möglichkeit hat, die Typen zu prüfen und das i.A. auch tut.

Ein Compiler muss 'printf("%d", 2.0)' zumindest übersetzen. Warnungen
bezüglich nichtpassender Typen sind mir nur vom gcc geläufig, und auch
da nur für hinreichend konstante Formatstrings.

Was freilich selten der Fall ist. Meistens werden die
Formattierungsketten erst zur Laufzeit aus einer Datei gelesen.

--
James Kanze (GABI Software) email:james.kanze (AT) gmail (DOT) com
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
Back to top
James Kanze
Guest





PostPosted: Thu Apr 19, 2007 3:05 pm    Post subject: Re: printf() Reply with quote

On Apr 17, 5:39 pm, Christoph Bartoschek <bartosc...@gmx.de> wrote:
Quote:
Sebastian Bormann wrote:
Kann mir jmd bitte den Unterschied zwischen printf() und cout
erklären.

printf hat auch den Vorteil, dass man einfach die Stellen hinter dem Komma
bei Gleitkommazahlen bestimmen kann.

Geht genauso gut mit ostream, finde ich.

--
James Kanze (GABI Software) email:james.kanze (AT) gmail (DOT) com
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
Back to top
James Kanze
Guest





PostPosted: Thu Apr 19, 2007 3:12 pm    Post subject: Re: printf() Reply with quote

On Apr 17, 7:42 pm, Dirk Clemens <lemmid...@ftb-net.de> wrote:

Quote:
Ich würde eher sagen: print() und cout sind 2 verschiedene Philosophien,
von denen *ich* auch unter C++ die printf()-Varianten klar vorziehe,
weil ich sie für viel einfacher und übersichtlicher halte.

ostream bietet wesentlich mehr Funktionalitäten an. Der
philosophische Unterschied liegt ehe darin, dass die printf
Familien geschlossen ist: man hat, was sie anbietet, und nichts
mehr; ostream ist dagegen eine offene Baukiste relativ
niedrigerer Ebene, womit man alles machen kann, muss aber auch
meistens selber etwas machen.

Für Anfänger ist auch ostream etwas einfach zu benutzen. Wenn
man aber auf dieser Ebene bleibt, dann wird printf schnell
interessanter. Dagegen wenn man ostream richtig lernt und
benutzt, hat man schell den Gefühl, dass es bei printf ziemlich
viele Möglichkeiten fehlen: wie mache ich z.B. die Ausgabe einer
Decimal (Benutzer definiertes Typs) nach einem Socket?

--
James Kanze (GABI Software) email:james.kanze (AT) gmail (DOT) com
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
Back to top
Thomas Maeder
Guest





PostPosted: Thu Apr 19, 2007 9:07 pm    Post subject: Re: printf() Reply with quote

Jirka Klaue <klaue (AT) dresearch (DOT) de> writes:

Quote:
printf ist eine globale Funktion, die als ersten Parameter einen
Zeiger auf einen Formatstring erwartet. Alle weiteren Parameter
können beliebig sein, denn es handelt sich um eine variable
Argumentliste. Welche Parameter printf im Einzelnen braucht, steht
im Formatstring. Es gibt jedoch weder für den Compiler zur
Übersetzungszeit noch für die Funktion printf zur Laufzeit die
Möglichkeit zu prüfen, ob tatsächlich die erwarteten Parameter
übergeben wurden.

Ich hoffe, Dir ist klar, daß der Compiler selbstverständlich die
Möglichkeit hat, die Typen zu prüfen und das i.A. auch tut.

Auch wenn der Formatstring aus einer (z.B. Sprach-) Datenbank kommt?
Back to top
Stefan Reuther
Guest





PostPosted: Thu Apr 19, 2007 10:50 pm    Post subject: Re: printf() Reply with quote

Björn Hendriks wrote:
Quote:
Dirk Clemens wrote:
Björn Hendriks wrote:
Beispiel mit 32 bit-Integern:

printf("Zahl %d, Buchstabe %c\n", 'x', 3Cool;

Hier wird printf das 'x' und die ersten drei Bytes des Integers 38 als
Integerzahl interpretieren und das letzte Byte der 38 als Buchstaben, du
erhältst also etwas völlig anderes als erwartet, ohne dass du irgendwie
gewarnt würdest, denn printf ist nicht typsicher.

Für einen erfahrenden C-Programmierer ist die Ausgabe sofort und
schnell nachzuvollziehen und keinesfalls unerwartet.

Wenn man sich lange mit printf auseinandergesetzt hat, kennt man natürlich
dessen Tücken und kann damit umgehen.

Dein Beispiel ist eigentlich recht einfach. Es wird zuerst der
(ASCII-)Code von 'x' ausgegeben ('x' wird als Parameter einer
variadischen Funktion auf int promoted und ergibt damit genau das, was
'%d' erwartet), danach das (ASCII-)Zeichen #38 ('%c' erwartet einen
int). Da ist nix mit Bytes umsortieren.

Problematisch ist eher sowas wie
printf("Zahl %d, Text %s\n", somestring, 99);
und bei aus Eingabedaten generierten Formatstrings
strcpy(eingabedaten, "foo %n");
printf(eingabedaten, somestring);
(gutartige Eingabedaten enthalten %s statt %n).

Quote:
Ich würde eher sagen: print() und cout sind 2 verschiedene Philosophien,
von denen *ich* auch unter C++ die printf()-Varianten klar vorziehe,
weil ich sie für viel einfacher und übersichtlicher halte.

Das ist eine Frage der Übung. Als ich vor 20 Jahren mit C angefangen hatte,
gab es nichts anderes und ich habe es aus Gewohnheit zunächst
weiterbenutzt, als ich mit C++ angefangen hatte. Inzwischen habe ich mich
so sehr an cout gewöhnt, dass ich printf gar nicht mehr benutze.

Man kann die Erweiterbarkeit von cout und die Bequemlichkeit von printf
gut kombinieren. Es gibt mehrere Implementationen eines typsicheren
Formatierers, das ist auch hier schon mehrfach diskutiert worden. Der
letzte Thread war meines Wissens "Vermengung von C und C++" vom Dezember
2006 (OP: Message-ID: <4u221rF16jjbuU1 (AT) mid (DOT) individual.net>).


Stefan
Back to top
Stefan Reuther
Guest





PostPosted: Thu Apr 19, 2007 11:00 pm    Post subject: Re: printf() Reply with quote

Hallo,

Andreas Huennebeck wrote:
Quote:
Stefan Reuther wrote:
Historische Implementationen von iostream waren gerne mal langsamer als
stdio, einfach deswegen, weil sie im Hintergrund stdio aufgerufen haben

Ich habe mit dem (damals aktuellen) gcc von 2005 festgestellt, daß
eine Konstruktion mit ostringstream um etwa Faktor 150 langsamer
war als eine mit sprintf; der Code sah im Prinzip etwa so aus:

Dein Programm leicht modifiziert:
----8<----
#include <sstream>
#include <iostream>
#include <stdio.h>

int main(int argc, char** argv) {
double data[1000];
for (int i = 0; i < 1000; ++i) data[i] = i*i;

int num = atoi(argv[1]);
for (int zz = 0; zz < num; ++zz) {

#if USE_SPRINTF
std::string output;
for (int i = 0;i < 1000; ++i)
{
char buf[128];
snprintf(buf, 128, "%f ", data[i]);
buf[127] = '\0';
output += buf;
}
#else
std::ostringstream oss;
for (int i = 0;i < 1000; ++i)
{
oss << data[i] << " ";
}
std::string output = oss.str();
#endif
}
}
----8<----

Damit erhalte ich hier folgendes:

----8<----
royale:~ > g++ -O2 -DUSE_SPRINTF=1 -o sprintf.exe strstr.cc
royale:~ > time ./sprintf.exe 100

real 0m3.234s
user 0m3.218s
sys 0m0.000s
royale:~ > g++ -O2 -DUSE_SPRINTF=0 -o stream.exe strstr.cc
royale:~ > time ./stream.exe 100

real 0m2.844s
user 0m2.858s
sys 0m0.000s

royale:~ > g++ --version
g++ (GCC) 3.4.4 (cygming special) (gdc 0.12, using dmd 0.125)
Copyright (C) 2004 Free Software Foundation, Inc.
----8<----

Die Stream-Version ist _bei mir_ also schneller.

Das hängt massiv von der Art der verwendeten Bibliothek ab. Dem
sprintf-Code ist die Optimierungseinstellung hinreichend egal, während
Nichtoptimierung bei einer auf Templates basierenden Bibliothek tödlich
ist. (In obigem Fall macht das Weglassen der Optimierung keinen
Unterschied, möglicherweise aber bei dir.)


Stefan
Back to top
Dirk Clemens
Guest





PostPosted: Fri Apr 20, 2007 12:43 am    Post subject: Re: printf() Reply with quote

Thomas Maeder wrote:
Quote:
Auch wenn der Formatstring aus einer (z.B. Sprach-) Datenbank kommt?
Wenn der Formatstring aus einer Datenbank kommen soll, dann eigent

sich cout überhaupt nicht. Und das ist ein klares Plus für prinft().

Dirk
Back to top
Christoph Bartoschek
Guest





PostPosted: Fri Apr 20, 2007 1:10 am    Post subject: Re: printf() Reply with quote

James Kanze wrote:

Quote:
On Apr 17, 5:39 pm, Christoph Bartoschek <bartosc...@gmx.de> wrote:
Sebastian Bormann wrote:
Kann mir jmd bitte den Unterschied zwischen printf() und cout
erklären.

printf hat auch den Vorteil, dass man einfach die Stellen hinter dem
Komma bei Gleitkommazahlen bestimmen kann.

Geht genauso gut mit ostream, finde ich.

Ok, könntest du mir zeigen, wie ich Gleitkommazahlen mit zwei Stellen hinter
dem Komma genauso gut rausschreiben kann?

Ich hab da bisher nichts gefunden, außer durch Stringmanipulation.

Christoph
Back to top
Heinz Saathoff
Guest





PostPosted: Fri Apr 20, 2007 6:22 pm    Post subject: Re: printf() Reply with quote

Moin,

James Kanze schrieb...
Quote:
Ich hoffe, Dir ist klar, daß der Compiler selbstverständlich die
Möglichkeit hat, die Typen zu prüfen und das i.A. auch tut.

Bei printf in keinem Fall. Wie kann er, wenn die erst zur
Laufzeit bekannt sind?

Solange der Formatstring als Literal bekannt ist, kann der Compiler das
schon überprüfen, z.B hier:

int x=12;
char ch='x';
double d=1.12;
printf("x=%2d d=%3.1f ch=%c\n", x, ch, d);

Nach den bekannten Regeln für den Formatstring kann der Compiler wissen,
dass die Reihenfolge der Parameter int,double,char sein soll, aber
tatsächlich int,char,double übergeben werden. Eine Warnung könnte so
lauten:
warning, parameter 2 (ch) is no float/double
warning, parameter 3 (d) is no char

Wie schon angesprochen hat der Compiler nur Probleme bei erst zur
Laufzeit feststehendem Formatstring, z.B. hier:

const char* GetFormatString();
// ...
printf(GetFormatString(), x, ch, d);


- Heinz
Back to top
Christoph Egger
Guest





PostPosted: Sat Apr 21, 2007 12:15 am    Post subject: Re: printf() Reply with quote

Christoph Bartoschek schrieb:
Quote:
James Kanze wrote:

On Apr 17, 5:39 pm, Christoph Bartoschek <bartosc...@gmx.de> wrote:
Sebastian Bormann wrote:
Kann mir jmd bitte den Unterschied zwischen printf() und cout
erklären.
printf hat auch den Vorteil, dass man einfach die Stellen hinter dem
Komma bei Gleitkommazahlen bestimmen kann.
Geht genauso gut mit ostream, finde ich.

Ok, könntest du mir zeigen, wie ich Gleitkommazahlen mit zwei Stellen hinter
dem Komma genauso gut rausschreiben kann?

Ich hab da bisher nichts gefunden, außer durch Stringmanipulation.

Christoph

float f = 1.23456;
std::cout.precision(2);
std::cout << f;
Back to top
Post new topic   Reply to topic    C++Talk.NET Forum Index -> C++ (German) All times are GMT
Goto page Previous  1, 2, 3, 4  Next
Page 2 of 4

 
 


Powered by phpBB © 2001, 2006 phpBB Group