Forum: Compiler & IDEs Array in funktion übergeben


von Ich (Gast)


Lesenswert?

Hi,
also ich versuche seit stunden einfach nur einen array in eine C 
funktion zu übergeben (AVR GCC und Studio 4).
Egal was ich mache, es ist einfach nicht möglich. Ich habe unzählige 
verschiedene varianten im Netzt gefunden. Aber egal wie ich meinen code 
ändere, es gibt immer die selbe fehlermeldung und das Programm funzt 
nicht richtig
../mt.c:49: warning: passing argument 1 of 'myfunc' from incompatible 
pointer type
).
Ich habe ernsthaft überlegt, GCC zu deinstallieren und ausschliesslich 
BASCOM zu benutzen.

Hier ist wie ich es gemacht habe:

erstmal in main() das array deklariert und die funktion aufgerufen:

char txt[100];
txt[0]='a'
txt[1]='b'
txt[2]='c'
txt[3]='d'
txt[4]='e'
myfunc(txt); -> funzt nicht

myfunc("hallo"); -> funzt

und dann in der funktion:

void myfunc(char *text){
while(*text){
...
text++;}
}

und der prototyp:
void myfunc(char *text);

Was ist hier falsch 
???????????????????????????????????????????????????????????????????????? 
???????????????????????????????????????????


Danke
Grüße

von Peter (Gast)


Lesenswert?

char txt[100];
myfunc(txt); -> funzt nicht
void myfunc(char *text);

char* ist halt nicht gleich char[100] - ist ja auch bloss eine Warnung, 
es geht aber. Um die warnung nch wegzubekommen must du casten.

myfunc((char*)txt);

von Random .. (thorstendb) Benutzerseite


Lesenswert?

char txt[100];
txt[0]='a'
txt[1]='b'
txt[2]='c'
txt[3]='d'
txt[4]='e'
myfunc(txt); -> funzt nicht

myfunc("hallo"); -> funzt

und dann in der funktion:

void myfunc(char *text){
while(*text){
...
text++;}
}



der Fehler liegt auch noch woanders:
txt[5]='\0'

Zum cast:

myfunc(&txt[0]); sollte immer funzen.


VG,
/th.

von Ich (Gast)


Lesenswert?

Danke, das funzt!
Aber woher sollte ich sowas wissen? Warum steht das nirgends?
Grüße

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Der Array-Pointer-Dualismus ist hier kein Problem.

Jedoch ist das von Hand initialisierte Array nicht nullterminiert - es 
fehlt schlichtweg ein

  txt[5] = 0;

Und außerdem nach jeder einzelnen Zeile mit der Initialisierung ein 
Semikolon.

Im übrigen ist "funzt nicht" die dümmste aller nur denkbaren 
Fehlerbeschreibungen.

von Mark B. (markbrandis)


Lesenswert?

Ich schrieb:
> Danke, das funzt!
> Aber woher sollte ich sowas wissen? Warum steht das nirgends?

Solches steht in manchem Buche.

von Stefan B. (stefan) Benutzerseite


Lesenswert?

1
void myfunc(char *text)
2
3
int main(void)
4
{
5
  char txt[100];
6
  txt[0]='a';
7
  txt[1]='b';
8
  txt[2]='c';
9
  txt[3]='d';
10
  txt[4]='e';
11
  txt[5]='\0'; // <== !!!
12
13
  myfunc(txt); 
14
  return 0;
15
}
16
17
void myfunc(char *text)
18
{
19
  while(*text)
20
  {
21
    > ...
22
    text++;
23
  }
24
}

von Random .. (thorstendb) Benutzerseite


Lesenswert?

Hier und da geändert :-)
1
 
2
 void myfunc(char *text);
3
 
4
 int main(void)
5
 {
6
   char txt[100]="abcde";
7
 
8
   myfunc(txt);
9
   return 0;      // return auf uC? okok, es gibt die _sys_exit(), aber das ist doch nciht dein ernst??
10
 }
11
 
12
 void myfunc(char *text)
13
 {
14
   do
15
   {
16
     uart_putchar(*text);
17
   } while(*text++);
18
19
  //oder, sollte auch gehen:
20
    while(*text++) uart_putchar(*text);
21
 }


   }

;-)

von Helmut L. (helmi1)


Lesenswert?

Hier bei wird erst das Zeichen ausgegeben und dann auf '\0' geprueft.


void myfunc(char *text)
 {
   do
   {
     uart_putchar(*text);
   } while(*text++);
 }


Besser ist es zuerst auf '\0' zu pruefen

void myfunc(char *text)
 {
   while(*text)
   {
     uart_putchar(*text++);
   }
 }

sonst gibt man '\0' mit aus.

gruss Helmi

von Random .. (thorstendb) Benutzerseite


Lesenswert?

jep, weiss ich.
Hatte nur irgendwo mal das prob, dass ich die null auch brauchte.

Normalerweise mach ich auch while(*buf) out(*buf++);


VG,
/th.

von Mark B. (markbrandis)


Lesenswert?

>return auf uC? okok, es gibt die _sys_exit(), aber das ist doch nciht dein 
>ernst??

Laut ANSI-C (C99) muss main() einen Wert zurückliefern (int).
Dass main() auf manchen Systemen nie verlassen wird - die typische 
Endlosschleife bei Embedded-Systemen eben - daran haben die Ersteller 
des Standards vielleicht nicht gedacht ;-)

von Ich (Gast)


Lesenswert?

Also erstmal vielen dank für die Antworten.

Offenbar hab ich mein Problem nicht genau genug beschrieben.
Das in meinem Beispiel die ; fehlen war mir schon klar, und in meinem 
eigentlichen code war auch ein =0; vorhanden. Es ging auch nur darum, 
die methodik der array übergabe darzustellen. Immerhin war das ja meine 
Frage, wie ich den Array fehlerfrei in die funktion übergeben kann, und 
nicht wie die Syntax von c ist.
myfunc(&txt[0]); hat den Fehler auch hervorgerufen.

@Rufus: falls du meinen gesammten post durchgelesen hast dann hättest du 
genau gesehen, was für eine Fehlermeldung ich erhalten habe. Und auf 
genau diesen Fehler bezieht sich das "funzt nicht". Insofern war nicht 
meine Beschrwibung das Dumme ;-)

Grüße

von Peter (Gast)


Lesenswert?

> Laut ANSI-C (C99) muss main() einen Wert zurückliefern (int).
richtig, aber es muss keine return geschrieben werden

von Mark B. (markbrandis)


Lesenswert?

Peter schrieb:
>> Laut ANSI-C (C99) muss main() einen Wert zurückliefern (int).
> richtig, aber es muss keine return geschrieben werden

Eh? Also sowas:
1
int main()
2
{}

wird ein standardkonformer Compiler wohl eher nicht akzeptieren. Obwohl, 
ich seh grad, ist nur ne Warning und kein Error. Zumindest mit gcc 
3.4.5.

von Stefan B. (stefan) Benutzerseite


Lesenswert?

Ich schrieb:

> Offenbar hab ich mein Problem nicht genau genug beschrieben.
> Das in meinem Beispiel die ; fehlen war mir schon klar, und in meinem
> eigentlichen code war auch ein =0; vorhanden.

Hmm. Dann darfst du dich nicht wundern, wenn die Helfer zum falschen 
Problem antworten, wenn du Code mit eigentlich schon klaren Fehlern 
postest.

> Es ging auch nur darum,
> die methodik der array übergabe darzustellen. Immerhin war das ja meine
> Frage, wie ich den Array fehlerfrei in die funktion übergeben kann, und
> nicht wie die Syntax von c ist.
> myfunc(&txt[0]); hat den Fehler auch hervorgerufen.

Dein Problem ist dein while(*txt)...

Du führst das while so lange aus, wie der Inhalt deiner Arrayzelle 
ungleich 0 ist.

Wenn du bei der Definition des Arrays in main() keine 0 in das Array 
reinschreibst, ist das Beenden des while nicht vorhersagbar. Irgendwann 
kann zufällig eine 0 kommen, derweil läuft der Zeiger text in myfunc() 
Amok...

Wenn du in deinem Array txt neben Buchstaben, Ziffern auch eine 0 
ausgeben willst, kannst du das nicht mit while(*text) machen. Dann musst 
du z.B. die Länge deines Arrays mitgeben z.B.
1
void myfunc(char *text, unsigned char laenge)
2
3
int main(void)
4
{
5
  char txt[100];
6
7
  txt[0]='a';
8
  txt[1]='b';
9
  txt[2]=0;
10
  txt[3]='d';
11
  txt[4]='e';
12
13
  myfunc(txt, 5); 
14
  return 0;
15
}
16
17
void myfunc(char *text, unsigned char laenge)
18
{
19
  while(laenge)
20
  {
21
    ausgabe(*text++);
22
    laenge -= 1;
23
  }
24
}

Eine 2. Falle lauert auf µC:

Du legst das Array txt zur Laufzeit an (innerhalb main() und verlangst 
100 Bytes dafür, nutzt aber nur 5. Je nach µC ist da schnell der Platz 
im RAM weg und es kommt keine Fehlermeldung, wenn das passiert! Wenn du 
den Speicher mit char txt[] = "hello" anlegst, gehen nur 5+1 Zeichen 
drauf!

von Peter (Gast)


Lesenswert?

> wird ein standardkonformer Compiler wohl eher nicht akzeptieren. Obwohl,
> ich seh grad, ist nur ne Warning und kein Error. Zumindest mit gcc
> 3.4.5.
doch wird er, war vor kurzen hier im Forum erwähnt, es ist zulässig aber 
nur bei main.

von Random .. (thorstendb) Benutzerseite


Lesenswert?

1
void myfunc(char *text, unsigned char laenge)
2
{
3
  while(laenge--) ausgabe(*text++);
4
}

**g**
Ich liebe es kurz :-)

Ich bin allerdings von diesen längenangaben in meinem Programmen weg, 
zumindest dort, wo ich mit strings arbeite. Macht auf dauer nur 
probleme, z.B. beim Bearbeiten eines strings. old_len, new_len, tmp_len, 
... **argh**


VG,
/th.

von Karl H. (kbuchegg)


Lesenswert?

Ich schrieb:

> @Rufus: falls du meinen gesammten post durchgelesen hast dann hättest du
> genau gesehen, was für eine Fehlermeldung ich erhalten habe.

Und ich behaupte mal:

Wenn dein (vollständiges) Programm so aussieht, wie es in deinem 
Ursprungsposting angedeutet ist, dann kommt diese Warnung nicht.
Das was du gepostet hast, ist der normale und von C vorgesehene Weg, wie 
man ein Array an eine Funktion übergibt (indem der Name des Arrays zu 
einem Pointer auf das erste Array Element degradiert wird und dieser 
Pointer an die Funktion zugewiesen wird).

Weder der Cast, noch &txt[0] dürfen da irgendetwas daran ändern.

Dass du deinen 'String' falsch aufgebaut hast und daher deine Schleife 
innerhalb der Funktion nicht korrekt abbrechen wird, ist ein anderes 
Problem.


In diesem Sinne hat die Warnung, so sie sich überhaupt auf den Aufruf 
bezieht, nichts damit zu tun, dass dein Programm nicht funzt (was auch 
immer 'nicht funzt' bedeutet). Du scheinst immer noch der Auffassung zu 
sein: Wenn der Compiler nichts meldet, dann ist alles in Ordnung. Das 
ist ein Trugschluss.

von Karl H. (kbuchegg)


Lesenswert?

Mark Brandis schrieb:

> Eh? Also sowas:
>
>
1
int main()
2
> {}
3
> 
4
>
>
> wird ein standardkonformer Compiler wohl eher nicht akzeptieren.

Doch. Das muss er akzeptieren.

von Mark B. (markbrandis)


Lesenswert?

Aber nicht ohne Warnung.
Guter Code erzeugt keine Warnungen :-)

von Karl H. (kbuchegg)


Lesenswert?

Mark Brandis schrieb:
> Aber nicht ohne Warnung.
> Guter Code erzeugt keine Warnungen :-)

Im C-Standard gibt es keine Warnungen. Dort ist nur definiert, was als 
Fehler zu gelten hat.

Wenn dein Compiler da eine Warnung rauswirft, dann kann er das tun. 
Verpflichtet dazu ist er nicht.
1
int main()
2
{
3
}

ist laut C-Standarddokument ein 100% legales, dem C-Standard 
entsprechendes Programm. Da ist nichts falsch oder undefiniert. Jeder 
standardkonforme Compiler weiß, wie er das zu übersetzen hat. Und wenn 
er dieses Programm nicht richtig übersetzen kann, dann ist er 
genaugenommen nicht standardkonform.

Das ist dasselbe, wie ...
1
int main()
2
{
3
  int c;
4
5
  if( c = 5 )
6
    c = 8;
7
8
  return 0;
9
}

... ebenfalls ein dem C-Standard 100% entsprechendes Programm ist, auch 
wenn in der if-Bedingung eine Zuweisung vorkommt. Das dich dein Compiler 
freundlicherweise darauf aufmerksam macht, dass die Zuweisung 
möglicherweise nicht das ist was du wolltest, ist zwar nett von ihm aber 
wird vom Standard nirgends eingefordert. Einige Compiler warnen, andere 
nicht. Aber das Verhalten, was dieser Code bewirken soll und wie er das 
tut, ist 100% vom Standard definiert.

von Mark B. (markbrandis)


Lesenswert?

Warnings sind kein C-Standard? Echt jetzt? Hm, wieder was gelernt.

von Karl H. (kbuchegg)


Lesenswert?

Mark Brandis schrieb:
> Warnings sind kein C-Standard? Echt jetzt? Hm, wieder was gelernt.

Dein Compiler kann dich auch warnen, dass das Badewasser übergeht. 
Interessiert im C-Standard keinen Hund.

von Mark B. (markbrandis)


Lesenswert?

Hm, dann wiederum gibt es Sachen die der Standard verlangt, die aber bei 
Nichtbeachtung durchaus eher eine Warnung als einen Fehler erzeugen. 
(Bsp. "no newline at end of file"). Vielleicht daher meine Konfusion.

von Karl H. (kbuchegg)


Lesenswert?

Mark Brandis schrieb:
> Hm, dann wiederum gibt es Sachen die der Standard verlangt, die aber bei
> Nichtbeachtung durchaus eher eine Warnung als einen Fehler erzeugen.
> (Bsp. "no newline at end of file"). Vielleicht daher meine Konfusion.

Der Standard kennt nur 2 Zustände.
Entweder das Programm entspricht den Regeln oder es entspricht nicht. 
Alles was nicht entspricht ist automatisch ein Fehler und muss als 
solcher gemeldet werden.
Was dein Compiler dir als Zusatzleistung noch an Warnungen ausgibt, ist 
dem Standard egal.

Bisher reden wir nur von Syntaxfehlern, also Dingen die der Compiler zur 
Compilezeit erkennen muss.

Nun gibt es natürlich noch Fehler, die der Compiler nicht erkennen kann 
und die sich erst zur Laufzeit als Fehler bemerkbar machen. Davon gibt 
es im Standard 2 Stück:
  undefined behaviour
  unspecified behaviour

Der Unterschied ist etwas akademisch, denn ein Fehler ist es auf jeden 
Fall.
"unspecified behaviour" bedeutet, dass der Standard keine Vorgabe macht, 
was in so einem Fall zur Laufzeit passieren soll. Derjenige der den 
Compiler implementiert, kann sich etwas aussuchen. Wichtig aber: Was 
genau passiert muss dokumentiert werden und es muss immer gleich sein. 
Aber natürlich ist unspecified behaviour von Compiler zu Compiler 
verschieden.

Bei "undefined behaviour" hingegen ist alles erlaubt. Der Standard macht 
keine Vorgaben was passieren soll und es ist auch zulässig, wenn sich 
das Programm anders verhält, weil die Mondphase anders ist.

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

> int main()
> {
> }
>
> ist laut C-Standarddokument ein 100% legales, dem C-Standard
> entsprechendes Programm.

Ganz sicher? Das ist K&R-Syntax (oder C++), ich würde da ein 'void' in 
die runden Klammern schreiben.

von Karl H. (kbuchegg)


Lesenswert?

Rufus t. Firefly schrieb:
>> int main()
>> {
>> }
>>
>> ist laut C-Standarddokument ein 100% legales, dem C-Standard
>> entsprechendes Programm.
>
> Ganz sicher? Das ist K&R-Syntax (oder C++), ich würde da ein 'void' in
> die runden Klammern schreiben.

OK. zu schnell getippt und nicht drauf geachtet :-)

von Mark B. (markbrandis)


Lesenswert?

Ha! :-)

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.