www.mikrocontroller.net

Forum: Compiler & IDEs Kann keinen String zuweisen wieso ?


Autor: Micha (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

ich möchte einen ganz normalen String zuweisen aber irgendwie will der 
Compiler nicht... ich hab schon im Tutorial nachgeschaut und auch nach 
Anweisung gemacht.

Bitte um Hilfe !
char mode[7];

switch(test)
{
  case 0: mode = "Hallo"; break;
  case 1: mode = "Hello"; break;
}

sprintf(msg, "Test: %s", mode);


Autor: Peter (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Micha schrieb:
> ich hab schon im Tutorial nachgeschaut und auch nach
> Anweisung gemacht.

glaube ich nicht, weil sotwas in C nicht geht. Du musst den String 
Kopieren

strcpy(mode,"Hallo");

oder noch etwas sichere

strncpy(mode,"Hallo", sizeof(mode) );

Autor: elmo (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Das geht so:
strcpy(mode,"Hallo");

oder besser:
strncpy(mode,"Hallo",sizeof(mode));
Damit stellst du sicher, nicht über die Arraygrenzen hinauszuschreiben.

Autor: Peter (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
elmo schrieb:
> strncpy(mode,"Hallo",sizeof(mode));

schön das andere den gleichen fehler machen wie ich, richtig müsste es 
so sein:

strncpy(mode,"Hallo",sizeof(mode)-1);

Autor: Ein Gast (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
sprintf(mode,"Hallo");

geht auch, ist aber möglicherweise nicht ganz so performant.

Autor: elmo (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Peter schrieb:
> schön das andere den gleichen fehler machen wie ich, richtig müsste es
> so sein:
>
> strncpy(mode,"Hallo",sizeof(mode)-1);

Nein, das war schon korrekt so. Man kann aber (und sollte eigentlich), 
um sicher zu stellen, dass der neue String terminiert ist, 
dazuschreiben:
strncpy(mode,"Hallo",sizeof(mode));
mode[sizeof(mode)-1] = '\0';

Autor: A. K. (prx)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Peter schrieb:

>> strncpy(mode,"Hallo",sizeof(mode));

Soweit passt es, solange man sich konsequent darüber im Klaren ist, dass 
mode[] nicht zwangsläufig eine 0 hinten dran hat.

> strncpy(mode,"Hallo",sizeof(mode)-1);

Aber das das ist nun für sich allein wirklich falsch, weil es sich bei 
mode[] um eine nicht initialisierte lokale Variable handelt und im 
letzten Byte Müll statt 0 drin steht. Da fehlt noch:
  mode[sizeof(mode)-1] = '\0';

Siehe auch strlcpy, als besser konzipierte Version von strncpy.

Autor: Peter (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
[c]
char mode[7] = {0};

switch(test)
{
  case 0: strncpy( mode, "Hallo", sizeof( mode ) -1 ); break;
  case 1: strncpy( mode, "Hallo", sizeof( mode ) -1 ); break;
}

sprintf(msg, "Test: %s", mode);
[\]

so jetzt aber sollte es sauber sein.

Autor: A. K. (prx)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Peter schrieb:

> so jetzt aber sollte es sauber sein.

Nein. Nun steht im ersten Byte 0, aber im letzten steht immer noch Müll.

Formal korrekt in C99, aber Kandidat für den Schwachfugpreis, wäre
 char mode[7] = {0,0,0,0,0,0,0};
was aber bei lokalen Variablen und C89/C90 ebensowenig geht wie deine 
Version, weil sich solche Arrays nicht initialisieren lassen.

Autor: Peter (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
A. K. schrieb:
> Nein. Nun steht im ersten Byte 0, aber im letzten steht immer noch Müll.

das glaube ich nun nicht, weil es {0} meines wissen den completten 
string mit \0 anlegt.

Autor: A. K. (prx)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Peter schrieb:

> das glaube ich nun nicht, weil es {0} meines wissen den completten
> string mit \0 anlegt.

Hmm. Stimmt.

Autor: Pete K. (pete77)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Funktionieren sollte es auch mit sprintf.

Hast Du #include <stdio.h> und das Einbinden der Bibliothken beim Linker 
berücksichtigt?

Autor: Michael Buesch (mb_)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
A. K. schrieb:
> Peter schrieb:
>
>> so jetzt aber sollte es sauber sein.
>
> Nein. Nun steht im ersten Byte 0, aber im letzten steht immer noch Müll.
>
> Formal korrekt in C99, aber Kandidat für den Schwachfugpreis, wäre
>  char mode[7] = {0,0,0,0,0,0,0};
> was aber bei lokalen Variablen und C89/C90 ebensowenig geht wie deine
> Version, weil sich solche Arrays nicht initialisieren lassen.

eieiei. Ich würde dir mal zu einem guten C Buch raten. ;)

Autor: A. K. (prx)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Michael Buesch schrieb:

> eieiei. Ich würde dir mal zu einem guten C Buch raten. ;)

Wär wohl mal wieder nötig ;-). Denn meine einzige gute C-Einführung als 
Buch ist das K&R Original. Das originale Original wohlgemerkt. Da gehts 
wirklich nicht.

Autor: Michael Buesch (mb_)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
A. K. schrieb:
> Michael Buesch schrieb:
>
>> eieiei. Ich würde dir mal zu einem guten C Buch raten. ;)
>
> Wär wohl mal wieder nötig ;-). Denn meine einzige gute C-Einführung als
> Buch ist das K&R Original. Das originale Original wohlgemerkt. Da gehts
> wirklich nicht.

Wir haben mittlerweile ein neues Jahrtausend :P

Autor: A. K. (prx)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Michael Buesch schrieb:

> Wir haben mittlerweile ein neues Jahrtausend :P

C auch? Mein letzter Stand ist, dass es auch in aktualisierter Version 
noch vom letzten Jahrtausend stammt, wenn auch knapp.

Autor: Michael Buesch (mb_)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
A. K. schrieb:
> Michael Buesch schrieb:
>
>> Wir haben mittlerweile ein neues Jahrtausend :P
>
> C auch? Mein letzter Stand ist, dass es auch in aktualisierter Version
> noch vom letzten Jahrtausend stammt, wenn auch knapp.

Ich denke du weißt, dass ich das nicht ganz so gemeint habe wie es dort 
stand. ;)
Wer heute noch nach K&R schreibt hat aber trotzdem so etwa 30 Jahre 
Entwicklung verschlafen/ignoriert.

Autor: Micha (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Vielen Danke an alle !!
Mit der Methode:
strncpy(mode,"Hallo",sizeof(mode));

hat es funktioniert !

Gruß Micha

Autor: Michael Buesch (mb_)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Micha schrieb:
> Vielen Danke an alle !!
> Mit der Methode:
> strncpy(mode,"Hallo",sizeof(mode));
>
> hat es funktioniert !
>
> Gruß Micha

Ich hoffe du bist dir über das schon genannte NUL-terminator Problem 
damit bewusst.
— Function: char * strncpy (char *restrict to, const char *restrict from, size_t size)

...
    If the length of from is more than size, then strncpy copies 
just the first size characters. Note that in this case there is 
no null terminator written into to. 

Das muss in deinem Fall kein Problem sein. Man muss diesen Sonderfall 
nur kennen und entsprechend reagieren. Wenn strncpy für Benutzereingaben 
verwendet wird ist es sehr wichtig das Verhalten zu kennen.

Autor: Web-Applikator (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Warum überhaupt den String buchstabenweise kopieren, wenn er später 
sowieso mit sprintf nochmal umkopiert wird?

Wie wärs mit der Lösung:
const char * mode;

switch(test)
{
  case 0: mode = "Hallo"; break;
  case 1: mode = "Hello"; break;
}

sprintf(msg, "Test: %s", mode);

Autor: Rufus Τ. Firefly (rufus) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
A. K. schrieb:
> Michael Buesch schrieb:
>
>> eieiei. Ich würde dir mal zu einem guten C Buch raten. ;)
>
> Wär wohl mal wieder nötig ;-). Denn meine einzige gute C-Einführung als
> Buch ist das K&R Original. Das originale Original wohlgemerkt. Da gehts
> wirklich nicht.

Kennst Du die deutsche "Übersetzung" davon? Die wirkt so, als wäre sie 
von einem Automaten angefertigt, und die Idee, Sourcecode in einer 
Proportionalschrift zu setzen, ist auch eher bizarr.

Die zweite Ausgabe von Anfang der 90er hingegen ist in der Übersetzung 
richtig gut ...

'Ne neuere, die C99 beschreibt, gibts aber wohl nicht, wie?

Autor: A. K. (prx)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Rufus t. Firefly schrieb:

> Kennst Du die deutsche "Übersetzung" davon?

Nö. Hab indes schon davon gehört, vor einiger Zeit. Könnte ein gewisser 
Rufus gewesen sein, der schon damals drüber wetterte ;-). Ich hatte mir 
schon früh angewöhnt, lieber im englischen Original zu lesen. Auch 
angesichts von IBMs deutscher Version des technischen Handbuchs vom 
PC/XT (was ist ein Einheitenverstärker?) und Motorolas Übersetzung des 
68000 Manuals, die ein Freund deshalb gegen mein englisches 
Zweitexemplar eintauschte.

Autor: Rufus Τ. Firefly (rufus) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Das mag gut sein, daß Du da was von mir gelesen hast. Ich habe beide 
Ausgaben.

Davon abgesehen bevorzuge ich auch originalsprachige Literatur; in den 
letzten 20 Jahren waren über 90% aller Bücher, die ich gekauft habe, 
englischsprachig.

Merkwürdigerweise habe ich keinen englischen K&R. Habe ich bislang nie 
drüber nachgedacht, warum.

Achja, über IBM-"Deutsch" habe ich mich auch schon gefreut. "Serielle 
Zeigereinheit". Na, was ist das?

Autor: A. K. (prx)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Rufus t. Firefly schrieb:

> "Serielle Zeigereinheit". Na, was ist das?

Finde ich jetzt nicht so schlimm. Klingt zwar ein bischen beamtisch, ist 
aber immerhin fast korrekt und sogar leidlich verständlich. Sprachlich 
korrekter wäre freilich "zeigende Einheit" oder "zeigendes Gerät", aber 
Einheit ist in dem Kontext andersrum auch in IBM Englisch als "unit" 
recht verbreitet.

Autor: Klaus Wachtler (mfgkw)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ein Gast schrieb:
>
sprintf(mode,"Hallo");
>
> geht auch, ist aber möglicherweise nicht ganz so performant.

Nur fürs Archiv: so ziemlich die schlechteste Möglichkeit von
allen.
"nicht ganz so performant" ist noch beschönigend, und richtig
nett wird es, wenn irgendwann in dem zu kopierenden String
ein % steht und man nicht dran denkt, was das bewirkt.

Wieso schlägt man allen Ernstes so etwas vor, um einen
String zu kopieren?

Autor: Rolf Magnus (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Klaus Wachtler schrieb:
> Ein Gast schrieb:
>>sprintf(mode,"Hallo");
>>
>> geht auch, ist aber möglicherweise nicht ganz so performant.
>
> Nur fürs Archiv: so ziemlich die schlechteste Möglichkeit von
> allen.
> "nicht ganz so performant" ist noch beschönigend,

Na so langsam ist das nun auch wieder nicht. Davon abgesehen kann gcc 
das sogar optimieren.

> Wieso schlägt man allen Ernstes so etwas vor, um einen
> String zu kopieren?

Es hat zugegebenermaßen keinen Vorteil, aber so schlimm, wie du tust, 
ist es nun auch wieder nicht.

Autor: Michael Buesch (mb_)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Rolf Magnus schrieb:
> Klaus Wachtler schrieb:
>> Ein Gast schrieb:
>>>sprintf(mode,"Hallo");
>>>
>>> geht auch, ist aber möglicherweise nicht ganz so performant.
>>
>> Nur fürs Archiv: so ziemlich die schlechteste Möglichkeit von
>> allen.
>> "nicht ganz so performant" ist noch beschönigend,
>
> Na so langsam ist das nun auch wieder nicht.

Ja und es ermöglicht ganz nebenbei schöne Formatstring-attacken, wenn 
der string vom Benutzer vorgegeben werden kann.

> Davon abgesehen kann gcc das sogar optimieren.

Kann/könnte, oder tut er es wirklich in der Praxis?

Autor: Rolf Magnus (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Michael Buesch schrieb:
> Rolf Magnus schrieb:
>> Klaus Wachtler schrieb:
>>> Ein Gast schrieb:
>>>>sprintf(mode,"Hallo");
>>>>
>>>> geht auch, ist aber möglicherweise nicht ganz so performant.
>>>
>>> Nur fürs Archiv: so ziemlich die schlechteste Möglichkeit von
>>> allen.
>>> "nicht ganz so performant" ist noch beschönigend,
>>
>> Na so langsam ist das nun auch wieder nicht.
>
> Ja und es ermöglicht ganz nebenbei schöne Formatstring-attacken, wenn
> der string vom Benutzer vorgegeben werden kann.

Dann hat man sprintf falsch verwendet. Vom Benutzer übergebene Strings 
darf man grundsätlich niemals als Formatstring verwenden.

>> Davon abgesehen kann gcc das sogar optimieren.
>
> Kann/könnte, oder tut er es wirklich in der Praxis?

Er tut es in der Praxis, wobei das aber vermutlich davon abhängt, mit 
welcher libc man arbeitet.

Autor: A. K. (prx)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Rolf Magnus schrieb:

> Er tut es in der Praxis, wobei das aber vermutlich davon abhängt, mit
> welcher libc man arbeitet.

Der Compiler weiss, für welche libc er den Code übersetzt? Bei der 
libgcc würde das noch angehen.

Autor: Rolf Magnus (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
A. K. schrieb:
> Rolf Magnus schrieb:
>
>> Er tut es in der Praxis, wobei das aber vermutlich davon abhängt, mit
>> welcher libc man arbeitet.
>
> Der Compiler weiss, für welche libc er den Code übersetzt? Bei der
> libgcc würde das noch angehen.

Mag sein, daß es von der libc unabhängig ist. Jedenfalls hat gcc die 
Funktion sprintf (und so gut wie jede andere libc-Funktion) zu 
Optimierungszwecken schon selbst eingebaut und ruft nur dann die 
libc-Implementation auf, wenn er keine Möglichkeit für die Optimierung 
findet.
Siehe auch 
http://gcc.gnu.org/onlinedocs/gcc-4.5.1/gcc/Other-...

Autor: Marcus Harnisch (mharnisch) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Rolf Magnus schrieb:
> Jedenfalls hat gcc die
> Funktion sprintf (und so gut wie jede andere libc-Funktion) zu
> Optimierungszwecken schon selbst eingebaut und ruft nur dann die
> libc-Implementation auf, wenn er keine Möglichkeit für die Optimierung
> findet.

Das geht aber nur, wenn sich die C-library nicht dagegen
wehrt. Standard "Bezeichner" (da wir grad beim Thema waren...) werden
mit #defines umgebogen, damit gcc sie nicht als solche erkennt und
optimiert. Du kannst Dir ja mal die counter insurgency Attacken der
glibc in stdio2.h anschauen. Das kann man wiederum mit der Definition
des Macros _FORTIFY_SOURCE verhindern.

Gruß
Marcus

Autor: Rolf Magnus (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Marcus Harnisch schrieb:
> Das geht aber nur, wenn sich die C-library nicht dagegen
> wehrt.

Also hängt es doch, wie schon vermutet, von der libc ab.

> Standard "Bezeichner" (da wir grad beim Thema waren...) werden
> mit #defines umgebogen, damit gcc sie nicht als solche erkennt und
> optimiert.

Das ist aber eigentlich nicht so richtig ISO-konform.

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.