Argumentliste- Problem
-
Naja bleicher Hund
,
machen sollte sie, daß ein String im Rahmen der zulässigen (unsigned int, min, max) Möglichkeiten ausgegeben und rückgelesen wird.
Mein Traumaufruf wäre
returnkey = EditIntAt(char x, char y, unsigned int * value, int min, int max, char far * format)
Aber das krieg' ich irgendwie nicht hin
, an dem Argumentlistenzeugs klemmt's immer irgendwie, nichtmal "format" krieg' ich so zu fassen, kommt nur Speichermüll raus.
Hilft das zur Präzisierung
-
pointercrash() schrieb:
machen sollte sie, daß ein String im Rahmen der zulässigen (unsigned int, min, max) Möglichkeiten ausgegeben und rückgelesen wird.
also du willst einen string, in dem ein 'int' wert ist, ausgeben und den 'int' wieder zurückbekommen aber der 'int' darf nur in einem gewissen bereich sein?
wozu dann die va_list?
versteh' ich nicht. ich glaub' du musste es noch genauer erklären...
-
pale dog schrieb:
also du willst einen string, in dem ein 'int' wert ist, ausgeben und den 'int' wieder zurückbekommen aber der 'int' darf nur in einem gewissen bereich sein?
wozu dann die va_list?
versteh' ich nicht. ich glaub' du musste es noch genauer erklären...
Ich hab's auch nicht verstanden, aber es scheint so, daß vsprintf() auf einem Argumentzeiger besteht
. Versuche ich ohne va_list auszukommen, sähe das z.B. so aus:
// *********************************************************** // ********** Integer bearbeiten ***************************** // *********************************************************** char EditIntAt(char x, char y,unsigned int * value, int min, int max, char space) { char length, backkey = 0; char far * format = malloc(5); char far * editstring = malloc(10); unsigned int wert; if (format) { format = "%- d"; format[2]= space + '0'; wert = *value; if (editstring) { length = vsprintf(editstring, format, wert); // [Warning(ccom):edit.c,line 160] mismatch prototyped parameter type do { backkey = EditStringAt(x,y,editstring, "0123456789"); sscanf( editstring, "%d", &wert ); } while ((wert > max) && (wert < min)); if (backkey == 13) *value = wert; free(editstring); } free(format); } return backkey; } // Aufruf: test = EditIntAt(0, 0, &test, 1, 8888, 4);
... und das wird an bezeichneter Stelle moniert. Ein
length = printf(format, wert);
hingegen wird ohne Murren korrekt verarbeitet. Die printf()- Ausgabe muß ich jedoch ins Nirvana schicken, weil der Standardkanal auf meine Debugger- Schnittstelle zeigt
und wenn ich das ändere, kriegen wiederum andere Projekte Probleme mit den geänderten Libs.
Tja, aber die Umleitung über einen Ausgabebuffer verlangt va_list - jetzt klarer, wo das Problem liegt
-
vsprintf() brauchst du nur, wenn du die Daten der variablen Argumentliste ausgeben willst. Für deine Zwecke reicht ein normales
sprintf(editstring,format,wert);
aus.
-
CStoll schrieb:
Für deine Zwecke reicht ein normales
sprintf(editstring,format,wert);
aus.Eben nicht, da format zwingend
const char * format
haben muß, deswegen führt das Compilat die Zeile
format[2] = space + '0';
nicht aus und ich habe so nicht die Möglichkeit, das Ausgabeformat zu beeinflussen. Und tatsächlich - es geht leider wirklich nicht
.
Noch 'ne Idee??
-
pointercrash() schrieb:
Eben nicht, da format zwingend
const char * format
haben muß,
Falsch. Du kannst nicht-const-Dinge an const-Parameter übergeben. Nur andersrum geht es nicht. Leg doch einfach ein hinreichend großes char-Array für deinen Formatstring an.
-
Kannst du DAS Problem mal genauer beschreiben? Du kannst doch problemlos einen normalen 'char*' an eine Funktion übergeben, die einen 'const char*' erwartet (umgekehrt geht es glücklicherweise nicht so einfach). Also was hat dein Compiler daran auszusetzen?
(btw, vsprintf() erwartet genauso einen const char* als Formatangabe ;))
-
CStoll schrieb:
Also was hat dein Compiler daran auszusetzen?
Er legt format automatisch im ROM an (µC), wo Schreibzugriffe zur runtime nicht klappen.
CStoll schrieb:
(btw, vsprintf() erwartet genauso einen const char* als Formatangabe ;))
Richtig, da ist der Compiler in dieser Hinsicht freizügiger (format landet im RAM), besteht aber auf der Argumentliste
.
-
pointercrash() schrieb:
Er legt format automatisch im ROM an (µC), wo Schreibzugriffe zur runtime nicht klappen.
format ist bei dir nur ein Zeiger, der landet sicher nicht im ROM, weil er auf dem Stack liegt. Allenfalls landet das Literal, auf das du ihn zeigen lässt, dort. Darum sollst du ja auch ein Array benutzen.
-
Nochmal langsam: Worüber genau beschwert sich der Compiler bei so einem Quelltext (der Kern deines Programmes - etwas vereinfacht):
int wert=4711; char format[]="%- d",output[10]; format[2]='1'; sprintf(output,format,wert);
-
CStoll schrieb:
Nochmal langsam: Worüber genau beschwert sich der Compiler bei so einem Quelltext
Er beschwert sich nicht, format zeigt nur einfach auf's ROM und ich kann den Space nicht mit der gewünschten Ausgabebreite überschreiben, ich probier's mal mit 'nem Array ...
-
pointercrash() schrieb:
CStoll schrieb:
Nochmal langsam: Worüber genau beschwert sich der Compiler bei so einem Quelltext
Er beschwert sich nicht, format zeigt nur einfach auf's ROM und ich kann den Space nicht mit der gewünschten Ausgabebreite überschreiben, ich probier's mal mit 'nem Array ...
Wenn du den Formatstring als String-Literal angibst, ja (aber das hat nichts mit sprintf() zu tun). Deswegen mußt du die Daten auch in ein eigenes Array packen.
*genau hinsieht* Und so langsam erkenne ich auch den Fehler in deinem obigen Programm:
char far * format = malloc(5); char far * editstring = malloc(10); unsigned int wert; if (format) { format = "%- d"; format[2]= space + '0'; ... free(format); }
Zeile 7 kopiert NICHT den Inhalt des String-Literals in den Speicherbereich, den du in Zeile 1 angefordert hast, sondern biegt den Zeiger 'format' um auf die Adresse dieses Literals (im ROM). Das bewirkt einerseits ein Speicherleck (bei der Zuweisung verlierst du die Adresse des 5-Byte-Blockes aus Zeile 1) und andererseits Zugriffsfehler in Zeile 8 (das Literal liegt im ROM) und 10 (der Zeiger zeigt auf nichts, was von malloc() bereitgestellt wurde). Wenn du die Stringdaten kopieren willst, mußt du dazu strcpy() verwenden.
-
MFK schrieb:
format ist bei dir nur ein Zeiger, der landet sicher nicht im ROM, weil er auf dem Stack liegt. Allenfalls landet das Literal, auf das du ihn zeigen lässt, dort. Darum sollst du ja auch ein Array benutzen.
Jaaaa, war schon so gemeint, daß format ins ROM zeigt und nicht dort liegt
Soo, einchar format[5] = "%- d"
läßt format auf den Frame zeigen, damit klappt auch das Überschreiben des spaces mit der Ausgabebreite, das vergessene free(format) ist erwiesenermaßen ungesund
, aber jetzt klappt alles.
Meine Herren, ich bedanke mich für Ihre Beihilfe!!!
-
CStoll schrieb:
Zeile 7 kopiert NICHT den Inhalt des String-Literals in den Speicherbereich, den du in Zeile 1 angefordert hast, sondern biegt den Zeiger 'format' um auf die Adresse dieses Literals (im ROM).
Stimmt, das war ein böser Fehler, danke für den Hinweis, das könnte auch eine andere Sache erklären (ganz woanders).
Danke nochmals!!