Forum: Compiler & IDEs Warum diese Warnung?


von R. Q. (timebeast)


Lesenswert?

Hallo Leute,
hab gerade nen kleines Problemchen mit der Übergabe von Char-Feldern, 
sprich Strings. Hier mal ein kleines Beispiel Programm welches das 
Verhalten hat:
1
#include <avr/io.h>
2
3
void Versuch (unsigned char *Daten);
4
5
6
int main(void){
7
  
8
  unsigned char Test[5];
9
10
  *Test="Hallo";
11
12
  Versuch(Test);
13
14
return 0;
15
}
16
17
18
void Versuch (unsigned char *Daten){
19
  int irgendwas=0;
20
  irgendwas+=irgendwas;
21
}

Dieses Programm erzeugt eine Warning:
../Uebergabe_Test.c:10: warning: assignment makes integer from pointer 
without a cast

Kann mir jemand sagen was ich falsch mache?

Vielen Dank im vorraus

Ralf

von Ronny (Gast)


Lesenswert?

Dein Code legt ein Array für 5 Bytes an,dein String ist allerdings 
länger,nämlich 10 Bytes für den Text und eines für die Ende-Kennung 
0x00. Also 11 Byte.
1
char  Test[5];
2
*Test="Hallo welt";

Deine zweites Problem besteht im Ausdruck (*Test). Der derefernziert 
nämlich die Variable Test,d.h. du versuchst der Speicherstelle wo "Test" 
liegt einen Wert zu zuweisen. Und das Stringliteral "Hallo Welt" gibt in 
dem Fall einen Zeiger(!) auf den besagten String zurück. Und der wird 
dann in Test geschrieben.

Da Test allerdings dem Compiler nur als 8-Bit Wert bekannt ist,wundert 
es mich etwas dass da kein Fehler gemeldet wird oder zumindest ein "Loss 
in precision".

Vorschlag:
1
void func1(char *str)
2
{
3
 //...
4
}
5
6
void main(void)
7
{
8
char test1[] = "Hallo Welt";  // Als Array
9
char *test2  = "Hallo Welt";  // Als Pointer
10
11
func1(&test1[0]);  // Zeiger auf 1.Byte übergeben
12
func1(test1);      // Startadresse übergeben
13
14
func1(test2);      // Zeigervariable übergeben
15
}

von Uhu U. (uhu)


Lesenswert?

*Test ist dasselbe wir Test[0]

Die Fehlermeldung ist etwas irreführend, aber C-typisch:

Test ist für den Compiler ein konstanter Zeiger auf 5 unsigned char. 
*Test wird auf int erweitert.

   *Test = "Hallo";

bedeutet: Weise dem ersten Element die Adresse von "Hallo" zu. Das geht 
nur, wenn die Adresse - die ein Pointertyp ist - in int umgewandelt 
wird.

Da solche Sachen in aller Regel auf einen Fehler deuten, gibt der 
Compiler eine Warnung aus.


Du mußt also entweder

   unsigned char Test[5] = "Hallo";

schreiben - dann fehlt aber die abschließende \0 im String, darüber 
würdest du dann bei nächster Gelegenheit fliegen, oder, wenn du den 
String ändern willst:

   strcpy(Test, "Hallo");

was dir den Speicher zerklopft, weil das Ende von Test überschrieben 
wird.

Um diese Probleme zu umgehen, mußt du folgendermaßen vorgehen:

   unsigned char Test[] = "Hallo";     // Der Compiler reserviert 6 
chars

oder

   unsigned char Test[6];

   strcpy(Test, "Hallo");

von Oliver (Gast)


Lesenswert?

Versuch mal, dir den theoretischen und praktischen Unterschied zwischen
1
 char* test1 = "Hallo";
und
1
 char test2[] = "Hallo";

klar zu machen.

Oliver

von R. Q. (timebeast)


Lesenswert?

Hallo Oliver,
naja, das eine schreibt "Hallo" an die Speicheradresse wo test1 liegt, 
das andere erzeugt mir ein Array of Char mit der Größ0e 5 Char.

von Uhu U. (uhu)


Lesenswert?

R. Quentin wrote:
> naja, das eine schreibt "Hallo" an die Speicheradresse wo test1 liegt,

Das ist falsch.

   char* test1

erzeugt einen char pointer und

   char* test1 = "Hallo";

reserviert eine Stringkonstante im Speicher und initialisiert test1 mit 
deren Adresse.

Es gilt

   sizeof test1 == sizeof (char *)

Du solltest dich nochmal ausführlich mit den Grundlagen von C 
beschäftigen!

von R. Q. (timebeast)


Lesenswert?

Also nur mal so zum Verständnis, ein Pointer ist nichts weiter als ein 
Zeiger auf eine Speicheradresse, zumindest hab ich das mal so gelernt.

Also würde doch
char* test1
alleine geschrieben auf einen nicht näher spezifizierten (nicht 
initialisierten) Speicherbereich zeigen.

char* test1 = "Hallo";

>reserviert eine Stringkonstante im Speicher und initialisiert test1 mit
>deren Adresse.
ÄÄÄh, und was hab ich geschrieben: schreibt "Hallo" an die 
Speicheradresse wo test1 liegt, zwar nicht so umständlich ausgedrückt 
wie Du, aber doch exakt das selbe.

>Du solltest dich nochmal ausführlich mit den Grundlagen von C
>beschäftigen!
Bin ich genau in diesem Augenblick dabei ;-) und da gibt es dieses 
Warning was ich nicht verstehe...

von R. Q. (timebeast)


Lesenswert?

@Uhu Uhuhu:
entschuldigung, "umständlich" war falsch, exakt wollte ich schreiben! 
Sorry.

von Uhu U. (uhu)


Lesenswert?

> >reserviert eine Stringkonstante im Speicher und initialisiert test1 mit
> >deren Adresse.
> ÄÄÄh, und was hab ich geschrieben: schreibt "Hallo" an die
> Speicheradresse wo test1 liegt, zwar nicht so umständlich ausgedrückt
> wie Du, aber doch exakt das selbe.

test1 liegt nicht dort, wo der String "Hallo" steht. Was du schreibst 
ist definitiv falsch.

Im Speicher sieht das Ganze ungefähr so aus:
1
       Variable test1
2
       Adresse 100       Adresse 500
3
        ---------        -----------
4
        | 500   | -----> | "Hallo" |
5
        ---------        -----------

test1 liegt also z.B. auf Adresse 100, der String "Hallo" auf Adresse 
500.
Auf Adresse 100 steht 500 - nicht "Hallo"!

von R. Q. (timebeast)


Lesenswert?

Mist, ich merke gerade das das alles hier eh vergebliche Liebesmühen 
sind. Es ging mir ja explezit um die Zuweisung eines Strings in ein 
Array of Char. Ich wollte damit erreichen das ich halt nur einmal ein 
Array of Char erzeuge und dann halt, je nach Anforderung, verschiedene 
Strings hineinschreibe. Was mir halt gerad auffiel ist, wo speichert er 
wohl die "Zuweisungsstrings"?
Also kann ich mir auch gleich die gewünschte Anzahl Array of Char´s 
erzeugen und die dann explizit mit Namen übergeben. Damit fällt dieses 
ganze Pointer, reservierungs übergabe StringCopy Gemache weg.

Mit strcpy hat das ganze im übrigen geklappt, muß man halt noch die 
<string.h> includieren, und kann dann strings einem Char Array zuweisen 
(halt keine unsigned chars, naja). Aber das Programm wird durch den 
include der <string.h> auch nicht gerade kleiner ;-)

Gruß und danke für die Mühe
Ralf

von Uhu U. (uhu)


Lesenswert?

Es ging auch nur darum, dir den Unterschied zwischen den verschiedenen 
Möglichkeiten klar zu machen.

von R. Q. (timebeast)


Lesenswert?

Huch, tatsächlich, hab ich Mist geschrieben...ups, gemeint hatte ich 
aber,...
äääh, ja, nein, oky, du hast recht,.... aaargh, ärgerlich
("schreibt "Hallo" an die Speicheradresse die in test1 liegt")

Danke für die Mühe Uhu Uhuhu

P.S.: Nettes Bild :-)

von Rolf Magnus (Gast)


Lesenswert?

> Also nur mal so zum Verständnis, ein Pointer ist nichts weiter als ein
> Zeiger auf eine Speicheradresse, zumindest hab ich das mal so gelernt.

"Pointer" ist das englische Wort für "Zeiger".

> Also würde doch
> char* test1
> alleine geschrieben auf einen nicht näher spezifizierten (nicht
> initialisierten) Speicherbereich zeigen.

Ob der Speicherbereich initialisiert ist oder überhaupt existiert, weißt 
du nicht. Der Zeiger selbst ist nicht initialisiert, zeigt also einfach 
irgendwo hin.

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.