Forum: Compiler & IDEs Kann keinen String zuweisen wieso ?


von Micha (Gast)


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 !
1
char mode[7];
2
3
switch(test)
4
{
5
  case 0: mode = "Hallo"; break;
6
  case 1: mode = "Hello"; break;
7
}
8
9
sprintf(msg, "Test: %s", mode);

von Peter (Gast)


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) );

von elmo (Gast)


Lesenswert?

Das geht so:
1
strcpy(mode,"Hallo");

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

von Peter (Gast)


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);

von Ein Gast (Gast)


Lesenswert?

1
sprintf(mode,"Hallo");

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

von elmo (Gast)


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:
1
strncpy(mode,"Hallo",sizeof(mode));
2
mode[sizeof(mode)-1] = '\0';

von (prx) A. K. (prx)


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.

von Peter (Gast)


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.

von (prx) A. K. (prx)


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.

von Peter (Gast)


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.

von (prx) A. K. (prx)


Lesenswert?

Peter schrieb:

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

Hmm. Stimmt.

von Pete K. (pete77)


Lesenswert?

Funktionieren sollte es auch mit sprintf.

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

von Michael B. (mb_)


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. ;)

von (prx) A. K. (prx)


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.

von Michael B. (mb_)


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

von (prx) A. K. (prx)


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.

von Michael B. (mb_)


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.

von Micha (Gast)


Lesenswert?

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

hat es funktioniert !

Gruß Micha

von Michael B. (mb_)


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.
1
— Function: char * strncpy (char *restrict to, const char *restrict from, size_t size)
2
3
...
4
    If the length of from is more than size, then strncpy copies 
5
just the first size characters. Note that in this case there is 
6
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.

von Web-Applikator (Gast)


Lesenswert?

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

Wie wärs mit der Lösung:
1
const char * mode;
2
3
switch(test)
4
{
5
  case 0: mode = "Hallo"; break;
6
  case 1: mode = "Hello"; break;
7
}
8
9
sprintf(msg, "Test: %s", mode);

von Rufus Τ. F. (rufus) Benutzerseite


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?

von (prx) A. K. (prx)


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.

von Rufus Τ. F. (rufus) Benutzerseite


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?

von (prx) A. K. (prx)


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.

von Klaus W. (mfgkw)


Lesenswert?

Ein Gast schrieb:
>
1
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?

von Rolf Magnus (Gast)


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.

von Michael B. (mb_)


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?

von Rolf Magnus (Gast)


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.

von (prx) A. K. (prx)


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.

von Rolf Magnus (Gast)


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-Builtins.html#Other-Builtins

von Marcus H. (mharnisch) Benutzerseite


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

von Rolf Magnus (Gast)


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.

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.