Forum: Mikrocontroller und Digitale Elektronik Wozu der Zeiger in uart_puts(char *s) aus websitentutorial


von Julian K. (fragenkinsey)


Lesenswert?

Hallo Community,

ich belese mich gerade zum Thema UART auf dieser Website. Dabei bin ich 
auf den Beispielcode zu uart_puts() und zu uart_putc() gestoßen.

Dabei verstehe ich nicht, wozu man hierbei mit einem Zeiger arbeitet.

>void uart_puts (char *s)
>{
>    while (*s)
>    {   /* so lange *s != '\0' also ungleich dem "String-> 
>Endezeichen(Terminator)" */
>        uart_putc(*s);
>        s++;
>    }
>}

Wenn man schon mit einem Zeiger arbeitet, so hätte ich jetzt erwartet, 
dass man diesem eine Speicheradresse zuordnet. Warum arbeit man also 
hier mit einem Zeiger? Welche Adresse wird ihm zugeordnet?


Fg
fragenkinsey

: Bearbeitet durch User
von Karl H. (kbuchegg)


Lesenswert?

Julian Kinsey schrieb:

> Wenn man schon mit einem Zeiger arbeitet, so hätte ich jetzt erwartet,
> dass man diesem eine Speicheradresse zuordnet. Warum arbeit man also
> hier mit einem Zeiger? Welche Adresse wird ihm zugeordnet?

Die Frage ist eher:
Warum programmierst du in C, wenn du die einfachsten Grundlagen zur 
Stringverarbeitung, bzw. wie Arrays an Funktionen übergeben werden, 
nicht kennst?
1
  uart_puts( "hallo" );

und schon kriegt die Funktion ihren Zeiger übergeben.


Du brauchst ein C-Buch. So hat das alles wenig Sinn.

von B. S. (bestucki)


Lesenswert?


von Julian K. (fragenkinsey)


Lesenswert?

Ich hatte mal ein Jahr lang C in der Schule. Ich hatte gehofft, dass mir 
die Kenntnisse von damals ausreichen würden, um zumindestens das 
Tutorial nachzuvollziehen. Das scheint aber nicht zu funktionieren.

Müsste ich aber den Zeiger char *s nicht trotzdem z.B.: in int main () 
eine Adresse zuweisen, damit das Sinn ergibt. So wie ich das verstehe, 
wird jetzt "Hello" einfach auf den Zeiger char *s Hello übergeben. 
Diesem müsste ich doch aber vorher eine Speicheradresse für "Hello" 
zuweisen oder irre ich etwa?

Danke!

von Julian K. (fragenkinsey)


Lesenswert?

Danke für den Link. Ich werde ihn mir mal durchlesen.

FG
fragenkinsey

von B. S. (bestucki)


Lesenswert?

Du hast einen String, der ist irgendwo gespeichert. Wo spielt keine 
Rolle. Du übergibst dann deiner Funktion einen Zeiger auf den Anfang 
deines Strings. Mit dem Zeiger kann die Funktion nun auf einzelne 
Elemente des Strings zugreifen (ein String ist ja nichts anderes als ein 
char Array) und so ihre Arbeit erledigen.

Wenn du
1
uart_puts( "hallo" );
schreibst, übergibst du der Funktionen einen Zeiger, der auf den String 
"hallo" zeigt. Wo "hallo" gespeichert wird, kann dir egal sein.

Andere Möglichkeit:
1
char MeinText[]="hallo";
2
3
uart_puts(MeinText);
MeinText ist ein Zeiger auf das erste Element deines Strings. Man könnte 
auch schreiben:
1
uart_puts(&MeinText[0]);
Ist das selbe, aber unschön.


Wie bereits erwähnt wurde:
Karl Heinz schrieb:
> Du brauchst ein C-Buch. So hat das alles wenig Sinn.

von Hans Dampf (Gast)


Lesenswert?

Und weils so schön ist noch eine Möglichkeit:
1
char* MeinText = "hallo";
2
3
uart_puts(MeinText);
Der String "hallo" liegt irgendwo im Speicher. Die Zeigervariable 
MeinText enthält die Adresse des ersten Zeichens (hier 'h'). Diese 
Adresse wird an die Funktion übergeben.

Hier ist anders:
1
char MeinText[] = "hallo";
2
3
uart_puts(MeinText);
Es gibt ein Array (Speicherbereich) mit dem Namen MeinText, das 6 Byte 
groß ist. An diesem stehen die Zeichen "hallo" plus das 
Stringendezeichen '\0'.

Wenn man MeinText an eine Funktion übergibt, wird allerdings nicht der 
Speicherinhalt zur Funktion kopiert, sondern der Compiler übergibt die 
Adresse des ersten Elements des Arrays (bzw. des ersten Zeichens des 
Strings). Das ist eine Besonderheit bei Arrays (und damit Strings) in C.

von Julian K. (fragenkinsey)


Lesenswert?

Guten Abend,

ich glaube, dass ich es jetzt verstanden habe. Insbesondere dieser Satz

Hans Dampf schrieb:
> Das ist eine Besonderheit bei Arrays (und damit Strings) in C.

hat es mir klar gemacht. Danach viel es mir einfacher die letzten beiden 
Beiträge nachzuvollziehen.

In dem Tutorial sieht es ja so aus:

>int main(void)
>{
>   char s[7];
>   int16_t i = -12345;
>
>   uart_init();
>
>  itoa( i, s, 10 ); // 10 fuer radix -> Dezimalsystem
>  uart_puts( s );
>  .......}

und

>void uart_puts (char *s)
>{
>    while (*s)
>    {   /* so lange *s != '\0' also ungleich dem 
"String->Endezeichen(Terminator)" */
>        uart_putc(*s);
>        s++;
>    }
>}

ich war verwirrt, weil mir in der Hauptfunktion mindestens

char *s[7] statt char s[7]; (also das Zeigersymbol)

gefehlt hat. Ich meine, wenn die Definition der Funktion schon uart_puts 
(char *s) heißt, dann erwartet die Funktion einen Zeiger als übergebenes 
Argument. Das Array char s[7] muss aber nicht als Zeiger in int main() 
als Zeiger deklariert werden, weil es eine Sonderstellung hat. In C wird 
ein Array also quasi wie ein Zeiger betrachtet, sodass die Deklaration 
con char *s[7] bzw. "*" überflüssig wird - es reicht somit die 
Deklaration char s[7].

Über ein Feedback, ob ich das richtig verstanden habe, wäre ich erfreut.

Danke euch beiden.

FG
fragenkinsey

von Karl H. (kbuchegg)


Lesenswert?

Julian Kinsey schrieb:

> als Zeiger deklariert werden, weil es eine Sonderstellung hat. In C wird
> ein Array also quasi wie ein Zeiger betrachtet

Vorsicht mit dieser Aussage.

Viele Leute die so etwas oder etwas ähnliches sagen, meinen das Falsche.

Ein Array degeneriert in manchen Situationen zur Startadresse des Arrays 
im Speicher.

Zum Beispiel bei der Übergabe an eine Funktion.
Normale Variablen werden per Value übergeben. D.h. die Funktion bekommt 
eine Kopie des originalen Wertes des Aufrufers. Wie zb
1
void foo( int i )
2
{
3
  ....
4
}
5
6
int main()
7
{
8
  int j = 5;
9
10
  foo( j );
11
}

wird die Funktion foo aufgerufen, dann wird der Wert von j hergenommen 
(die 5), und davon eine Kopie in der lokalen Variablen i der Funktion 
foo abgelegt.

Arrays funktionieren anders. Steht der Name des Arrays alleine, dann 
degeneriert dieser zur Startadresse des Arrays im Speicher. Diese 
Startadresse wird dann für die Funktion in die Pointer Variable der 
Funktion kopiert.
1
void foo( int * daten )
2
{
3
  daten[0] = 5;
4
}
5
6
int main()
7
{
8
  int werte[8];
9
10
  foo( werte );
11
}

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.