Forum: Compiler & IDEs Basic c-frage: const char - Parameterübergabe?


von sverige (Gast)


Lesenswert?

Hallo,

Ich versuche gerade mir eine Debug-Routine zu schreiben die mir 
Zeichenketten über die Uart anzeigt. Ich habe dazu einen Uart treiber 
der eigentlich nur ein char array und die Länge davon braucht um das zu 
tun.

Jetzt bin ich gerade dabei mir das Unterprogramm Debug_MSG(const char 
buffer[]); zu schreiben welches ich dann so aufrufen möchte:

Debug_MSG("Hello World");

Dass soll dan weiters den Uart treiber aufrufen und eben ein Hello World 
ausgeben. Das funktioniert natürlch so einfach nicht, weil ich ja beim 
Aufrug des Unterprogramms die Information über die Länge des Strings 
verloren habe und somit nicht an den treiber weitergeben kann.

Die Alternativen:

Debug_MSG("Hello World", 11); //(Länge des Strings mitgeben)
Debug_MSG("Hello World\0"); //(String dann auf \0 parsen)

finde ich unschön.

Gibt es nicht irgendeinen Trick wie ich den const char[] an ein 
Unterprogramm weitergebe und dabei nicht durch die Pointer conversion 
die Länge des Strings verliere?? Extra jedes Mal eine Variable die dann 
den String enthält und global ist, bzw in ein struct verpackt möchte ich 
aben auch nicht. Vielleicht irgendwie mit Macros?

Das ganze klingt natürlich etwas kleinlich, aber wenn ich dafür eine 
geschickte Lösung finden würde, könnte ich die öfters einsetzen.

Also danke für Tipps!

lg

von Johannes M. (johnny-m)


Lesenswert?

Strings sind in C grundsätzlich automatisch nullterminiert! "Hello 
World" ist nicht 11, sondern 12 Zeichen lang, weil Du den Nullterminator 
am Ende vergessen hast.

Praktisch alle Funktionen in C, die sich mit der Auswertung und 
Verarbeitung von Strings befassen, werten den Nullterminator aus, so 
dass eine Übergabe der Stringlänge gar nicht erforderlich ist. Ein '\0' 
ist für eine solche Funktion das Zeichen, dass der String hier endet.

> Debug_MSG("Hello World\0"); //(String dann auf \0 parsen)
Der zusätzliche Nullterminator ist überflüssig. Und genau das auf '\0' 
parsen machen o.g. Funktionen, und das solltest auch Du machen.

von Karl H. (kbuchegg)


Lesenswert?

sverige wrote:

> Also danke für Tipps!

Der beste Tip ist immer noch: Kauf dir ein C-Buch. String Verarbeitung 
ist in C etwas essentielles. Ohne Literatur fällt man da ganz schnell 
auf die Schnauze.

Eine klitzekleine Einführung in die Stringverarbeitung mit den 
wichtigsten Stolpersteinen findest du hier:
http://www.mikrocontroller.net/articles/FAQ#Wie_funktioniert_String-Verarbeitung_in_C.3F

Aber das ist kein Ersatz für Literatur!

> Debug_MSG("Hello World\0"); //(String dann auf \0 parsen)

Siehst du, das mein ich mit Grundlagen. Auch konstante Strings sind per 
Definition immer automatisch mit einem \0 Zeichen abgeschlossen. Dafür 
sorgt der Compiler.

von Thomas P. (tpircher) Benutzerseite


Lesenswert?

1
Debug_MSG("Hello World\0"); //(String dann auf \0 parsen)

ist unnoetig, da C den String automatisch mit '\0' abschliesst. Das 
duerfte die sicherste Methode sein, wenn du unbedingt nur einen 
Parameter uebergeben willst.
Allerdings musst du dann in det Bebug_MSG() Funktion die Position des 
Stringterminators wieder ermitteln.

Eine andere (fehlertraechtige) Metode ist mit Makros:
1
#define Debug_MSG(s) Debug_MSG_Function(s, sizeof(s))
2
void Debug_MSG_Function(const char *str, size_t str_len);

Das funktioniert gut mit konstanten Strings, aber ein Code wie der 
folgende wird nicht mehr funktionieren
1
char *str = "hallo, das ist ein Debugstring"
2
Debug_MSG(str)

Denn sizeof(str) == sizeof(char *) == 2 oder 4 oder sonstwas, je nach 
Architektur.

von Karl H. (kbuchegg)


Lesenswert?

Thomas Pircher wrote:

> Allerdings musst du dann in det Bebug_MSG() Funktion die Position des
> Stringterminators wieder ermitteln.

Äh, nein.
Musst du nicht. Er fällt automatisch drüber, wenn er in einer Schleife 
die einzelnen Zeichen abarbeitet.
Sein Problem ist an dieser Stelle eigentlich nicht die Debug_MSG 
Funktion, sondern der UART-Treiber. Was er braucht ist eine uart 
Funktion die einen String ausgeben kann und nicht nur ein allgemeines 
char-Array (wofür er die Längenangabe tatsächlich brauchen würde). Bei 
einer String-Ausgabe jedoch, taucht die tatsächliche Stringlänge 
meistens nirgends explizit auf.

An dieser Stelle wäre alles andere (mittels Länge zu operieren) 
lediglich Murks. Vor allem, weil eine Stringausgabe nun wirklich kein 
Problem darstellt
1
void uart_puts( const char* str )
2
{
3
  while( *str )
4
    uart_putc( *str++ );
5
}

(uart_putc ist die Basisfunktion, die 1 Zeichen ausgeben kann. 
uart_puts ist die Erweiterung um einen kompletten String auszugeben)

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.