Shadax Geschrieben 29. August 2001 Geschrieben 29. August 2001 Ich will jetzt nicht drauf schwören, ob zusammengesetzte Strings zum Standard gehören, aber eigentlich sollte dieser Funktionsaufruf bis auf die fehlden Klammer legal sein: immerhin ist der erste Parameter von printf() ja ein `const char*', der lediglich aus mehreren `const char*'s zusammengesetzt ist. Genauso wie folgendes Code-Fragment: const char * const myStr = "Bugs " "Bunny"; printf("%s\n", myStr); Soweit ich weiss haben die gcc-Bauer mal ein Statement über zusammengesetzte Strings abgeben (leider kann ich es nicht mehr finden). Jedenfalls scheint sich gcc (2.95.2) im ANSI-Modus nicht darüber zu beschweren. Zitieren
Crash2001 Geschrieben 29. August 2001 Autor Geschrieben 29. August 2001 <BLOCKQUOTE><font size="1" face="Verdana, Arial, Helvetica, sans-serif">Zitat:</font><HR>Original erstellt von Shadax: <STRONG>Ich will jetzt nicht drauf schwören, ob zusammengesetzte Strings zum Standard gehören, aber eigentlich sollte dieser Funktionsaufruf bis auf die fehlden Klammer legal sein: immerhin ist der erste Parameter von printf() ja ein `const char*', der lediglich aus mehreren `const char*'s zusammengesetzt ist. Genauso wie folgendes Code-Fragment: const char * const myStr = "Bugs " "Bunny"; printf("%s\n", myStr); Soweit ich weiss haben die gcc-Bauer mal ein Statement über zusammengesetzte Strings abgeben (leider kann ich es nicht mehr finden). Jedenfalls scheint sich gcc (2.95.2) im ANSI-Modus nicht darüber zu beschweren.</STRONG> Zitieren
haddock Geschrieben 29. August 2001 Geschrieben 29. August 2001 @crash2001 OK, printf nimmt als Parameter genau einen const char*. Dieser enthält u.U. bestimmte Zeichenfolgen, die veranlassen, daß die Werte weiterer Variablen oder Konstanten an der entsprechenden Stelle in den String eingefügt werden. Alle Parameter werden durch Kommata getrennt. Die speziellen Formatzeichenfolgen werden immer durch ein '%' eingeleitet. Dabei korrespondieren diese mit den entsprechenden Variablen, das erste %x mit der ersten Variable usw. '%d' bedeutet, daß hier der wert einer ganzzahligen Variable/Konstante eingefügt werden soll. Ellipsenfunktionen haben nun die Eigenschaft, daß die Parameter als variable Liste vorliegen, wenn du jetzt versuchst, auf mehr Adressen zuzugreifen, al du in der Liste repräsentiert hast, wird dein Programm *irgendwo* lesen. Das dabei *irgendetwas* herauskommt, liegt auft der Hand, denn *irgendwo* muß ja nicht zwingend der Inhalt einer ganzzahligen Variablen stehen. Beim lesen gibt's übrigens noch nicht soviel Theater wie beim Schreiben, gelle :-) Klar soweit? Dein Aufruf müßte also so lauten: printf("J hat den Dezimal-Wert %d \nI hat den Dezimal-Wert %d \n", j, i); Für andere Datentypen gibt es noch eine ganze Anzahl weiterer Zeichenfolgen, man kann Anzahl der Nachkommastellen, Exponentialdarstellung uvm. veranlassen. auch @hasi: Manpage kommt demnächst. Hoffentlich hilfts schon mal ein Stück. Der Käptn Zitieren
MadMatrix Geschrieben 29. August 2001 Geschrieben 29. August 2001 Hallo erstmal! @Crash2001 <BLOCKQUOTE><font size="1" face="Verdana, Arial, Helvetica, sans-serif">Zitat:</font><HR> Aber was für Werte zeigt der denn dann an beim dritten und vierten %d an, wenn ich dahinter nicht die zu benutzenden Variablen hinschreibe? Weiss das vielleicht noch jemand? Zitieren
haddock Geschrieben 29. August 2001 Geschrieben 29. August 2001 @crash2001 <BLOCKQUOTE><font size="1" face="Verdana, Arial, Helvetica, sans-serif">Zitat:</font><HR> Schon klar, aber i, j kann man in dem Fall doch weglassen. MfG Crash2001 Zitieren
haddock Geschrieben 29. August 2001 Geschrieben 29. August 2001 @shadax Das mit den zusammengesetzten Strings funzt auch mit VC++, war mir überhaupt neu - man lernt halt nie aus... Der Käptn Zitieren
Crash2001 Geschrieben 29. August 2001 Autor Geschrieben 29. August 2001 Hi @captain... Also ich versteh das Posting von MadMatrix so, dass man die zusätzlich nur angeben muss, wenn man die entweder mehrmals anzeigen lassen will oder in ner anderen Reihenfolge als die vom Stack geholt wird angezeigt werde sollen. Ansonsten braucht man die so wie ich das sehe nicht. Tja, da kannst du sogar noch was von nem Newbie im Programmieren, wie ich es einer bin, was lernen. MfG Crash2001 <FONT COLOR="#a62a2a" SIZE="1">[ 29. August 2001 14:22: Beitrag 1 mal editiert, zuletzt von Crash2001 ]</font> Zitieren
haddock Geschrieben 29. August 2001 Geschrieben 29. August 2001 @crash2001 <BLOCKQUOTE><font size="1" face="Verdana, Arial, Helvetica, sans-serif">Zitat:</font><HR>Also ich versteh das Posting von MadMatrix so, dass man die zusätzlich nur angeben muss, wenn man die entweder mehrmals anzeigen lassen will oder in ner anderen Reihenfolge als die vom Stack geholt wird angezeigt werde sollen. Zitieren
maddin Geschrieben 29. August 2001 Geschrieben 29. August 2001 <BLOCKQUOTE><font size="1" face="Verdana, Arial, Helvetica, sans-serif">Zitat:</font><HR>Original erstellt von captain haddock: <STRONG> Das mit den zusammengesetzten Strings funzt auch mit VC++, war mir überhaupt neu - man lernt halt nie aus... Der Käptn</STRONG> Zitieren
MadMatrix Geschrieben 29. August 2001 Geschrieben 29. August 2001 Danke, maddin, dass du das Missverständnis geklärt hast! Zitieren
hoagi Geschrieben 29. August 2001 Geschrieben 29. August 2001 Hallöschen, um hier noch ein kleines Mißverständnis aufzulösen. natürlich findet die Funktion die Rücksprungadresse auch wenn die Anzahl der Parameter nicht mit denen im Formatstring übereinstimmt. Sie liegt nämlich ganz oben auf dem Stack. Zuerst werden die Parameter auf den Stack gelegt und dann die Funktion aufgerufen( und damit auch die Rücksprungadresse als letztes auf den Stack gelegt ). Andersrum wärs ja auch ein bisschen komisch. Zuerst die Funktion aufrufen und dann, quasi im Losfahren, die Parameter reinwerfen. Und auch die Bereinigung des Stacks ist kein Problem, da bei der C-Aufrufkonvention anders als z.B. bei Pascal ( und hier gibt es glaub ich auch keine Funktionen mit variabler Parameterliste ) der Aufrufende den Stack bereinigt und hier weiss der Compiler genau wieviel Daten er auf denselben gelegt. Wie gesagt bei Pascal wird der Stack vom aufgerufenden Program bereinigt und dafür gibsts dann parametrisierte Return - Assemblerbefehle. Vorteil dabei: Es wird etwas kleinere Programme erzeugt ( Man hat halt normalerweise mehr Funktionsaufrufe als Funktionen im Program). Hoagi :eek: :eek: :cool: Zitieren
Crush Geschrieben 29. August 2001 Geschrieben 29. August 2001 Also ich finde diese Methode wie der printf arbeitet irgendwie nicht gut. Änderungen von Meldungen und Texte könnten vielleicht ein Umdrehen von Ausgabewerten benötigen und dann müßte doch tatsächlich der ganze Mist neu kompiliert werden. Bei OCI gabs das Data-Binding. Da konnte ich einfach eine Variable mit einem Inhalt im Ausgabe oder Select-String verbinden. Das war was sinnvolles und praktisches. Gibt es für print-Ausgaben nicht auch sowas - oder müßte man sich das selber zusammenschustern? Zitieren
maddin Geschrieben 30. August 2001 Geschrieben 30. August 2001 <BLOCKQUOTE><font size="1" face="Verdana, Arial, Helvetica, sans-serif">Zitat:</font><HR>Original erstellt von hoagi: <STRONG>Hallöschen, um hier noch ein kleines Mißverständnis aufzulösen. natürlich findet die Funktion die Rücksprungadresse auch wenn die Anzahl der Parameter nicht mit denen im Formatstring übereinstimmt. Sie liegt nämlich ganz oben auf dem Stack. Zuerst werden die Parameter auf den Stack gelegt und dann die Funktion aufgerufen( und damit auch die Rücksprungadresse als letztes auf den Stack gelegt ). </STRONG> Zitieren
hoagi Geschrieben 30. August 2001 Geschrieben 30. August 2001 Hi Maddin, also prinipiell kann man den Stackpointer boshafterweise so verbiegen, daß die Rücksprungadresse nicht mehr passt, nur ist dies beim normalen Umgang mit zu übergebenden Parametern und lokalen Adressen nicht möglich. Diese werden nämlich mit stacküblichen Befehlen vom Stack geholt sondern über normale Speicherzugriffsbefehle z.B.: mov ax,[esp+10] ausgelesen. Der normale Vorgang ist aufrufendes Programm: push parameter1 push parameter2 ... push parametern call funktion auferufendes Programm: Sichern des Stackpointers Platz schaffen für lokale Variablen (sub esp,'Anzahl der für lokale benötigten Bytes ) Irgendwas Tun Sowohl Lokale Variblen werden als Speicher relativ zum Stackpointer angesprochen( nix push und nix pop ) Rücklesen des Stackpointers return aufrufendes Programm nach Funktionsaufruf: add,esp+'Anzahl Bytes die vorher übergeben worden sind' Der letzte Teil Unterscheidet sich nun bei C und Pascal. add,esp+'Anzahl Bytes die vorher übergeben worden sind' Fällt weg, dafür sieht Returnbefehl so aus: return 'Anzahl der übergenden Bytes' Aber du siehst ohne Bosshaft zu sein( oder Stack irgendwie zum überlaufen zu bringen ) bestehen eigentlich wenig Chancen, daß die aufgerufende Funktion die Rücksprungadresse verpasst. Oder hab ich dich irgendwie falsch verstanden. Hoagi Zitieren
Hasi Geschrieben 31. August 2001 Geschrieben 31. August 2001 <BLOCKQUOTE><font size="1" face="Verdana, Arial, Helvetica, sans-serif">Zitat:</font><HR>Original erstellt von captain haddock: <STRONG>@hasi: Manpage kommt demnächst. Hoffentlich hilfts schon mal ein Stück.</STRONG> Zitieren
haddock Geschrieben 31. August 2001 Geschrieben 31. August 2001 @Hasi: // Übliches Linux-ist-ganz-toll-Gefasel... Die gibt es, unterwww.linuxdoc.org/. Interessant ist die Serie 3 der manpages, die sich, auch unter dem Namen Linux Programmer Manual, auf die Funktionen der C-Library bezieht. Ich benutze auch viel MSVC, das hat als IDE schon viele nette Seiten. Ich reiße mich bestimmt nicht darum, jedes makefile von Hand zu schreiben Das MSDN mach halt auf mich oft den Eindruck von Flickwerk, und da bin ich froh, auch noch auf andere Quellen zuzugreifen zu können. Leider gibts fürs win32 API und für die MFC keine manpages, deswegen muß ich doch oft reinschauen Dr Käptn Zitieren
gajUli Geschrieben 1. September 2001 Geschrieben 1. September 2001 Hi Leuts, zum Problem einer Funktion mit variabler Parameterliste hab ich nochmal ein bisschen nachgelesen. int printf(const char*, ...); ist ja eine solche. C sieht zur Bearbeitung solcher Funktionen ein Makro namens ag_list vor sowie eine Lesefunktion, die das jeweils naechste Listenelement liefert. Jedoch wird das Ende nicht erkannt! Eine gaengige Loesung dieses Problems ist, dass der Programmierer solche Funktionen deshalb mit einer Paramerliste aufruft, die als letztes Argument einen Wert hat, der das Ende signalisiert. Bei printf() ist es anders: Die Anzahl der Zugriffe wird anhand der Anzahl der Prozentzeichen erkannt. Ist diese groesser als die Zahl der Argumente, so wird ein Zugriff auf etwas erzeugt, das nicht definiert ist. M. a. W., man erzeugt undefined behaviour (mal wieder). Da wir nichts weiter ueber die Implementierung von va_list wissen, ist auch die Annahme, was auf dem Stack passiert, nur eine Vermutung. Erinnern wir uns: undefined behavior == alles kann passieren. Uli Zitieren
haddock Geschrieben 3. September 2001 Geschrieben 3. September 2001 Toll, wie bei Toyota :-) Der alberne Käptn Zitieren
gajUli Geschrieben 3. September 2001 Geschrieben 3. September 2001 <BLOCKQUOTE><font size="1" face="Verdana, Arial, Helvetica, sans-serif">Zitat:</font><HR>Original erstellt von captain haddock: <STRONG>Toll, wie bei Toyota :-) </STRONG> Zitieren
haddock Geschrieben 4. September 2001 Geschrieben 4. September 2001 @EisenUli: <BLOCKQUOTE><font size="1" face="Verdana, Arial, Helvetica, sans-serif">Zitat:</font><HR> Anders als bei Autos gilt fuer Computerprogramme Murphy's Law. Zitieren
Crash2001 Geschrieben 4. September 2001 Autor Geschrieben 4. September 2001 Hi Da sieht man doch mal wieder, dass Murphys Law auch auf das Board zutrifft. Konnte grad schon wieder mal keine Verbindung herstellen. Und schon wieder...Ich probiers jetzt so lange aus, bis das hier eingetragen wird. MfG Crash2001 Zitieren
Empfohlene Beiträge
Dein Kommentar
Du kannst jetzt schreiben und Dich später registrieren. Wenn Du ein Konto hast, melde Dich jetzt an, um unter Deinem Benutzernamen zu schreiben.