Forum: Mikrocontroller und Digitale Elektronik C Programmierung Denkfehler?


von Alexander S. (amper)


Lesenswert?

Hi zusammen,

ich möchte eine Funktion in einer Funktion aufrufen (diese wird 
vordefiniert)
und der Rückgabe wert soll ein Array sein. Allerdings geht es nur wenn 
ich das array als global anlege. Könnte mir jemand erklären warum das so 
ist ?

Grundstrucktur des Programms:

//Defintions and Declaration:

unsigned short int    a;
unsigned short int    b;
unsigned short int    c;

unsigned short int array[3];   -> als globales Array funktioniert das 
Programm



// Function-Predefinitions:

unsigned short int func2()
{
        unsigned char i=0;
  unsigned short int s_a = 20;
  unsigned short int s_b = 40;
  unsigned short int s_g = 60;
  array[1]=s_a*2;
  array[2]=s_b*2;
  array[3]=s_g*2;
  return(array[i]);
}


void func1(void)
{

->  unsigned short int array[3]; => als lokales Array geht es nicht
    func2();
    th_U = times[1];
    th_V = times[2];
    th_W = times[3];
}


//MAIN

int main(void)
{
  func1();
  return 0;
}



Danke im vorraus für eure Hilfe

von Bernd H. (bhallinger) Benutzerseite


Lesenswert?

Ein Arry als Rückgabe geht nicht. Du must der Funktion einen Zeiger auf 
das Array übergeben. Dann kannst du in der Funktion das Array verändern.

von Sven P. (Gast)


Lesenswert?

Deine 'lokale' Variante:
Alexander S. wrote:
> unsigned short int func2()
> {
>         unsigned char i=0;
>   unsigned short int s_a = 20;
>   unsigned short int s_b = 40;
>   unsigned short int s_g = 60;
/*** array[...] ist hier nicht deklariert */
>   array[1]=s_a*2;
>   array[2]=s_b*2;
>   array[3]=s_g*2;
>   return(array[i]);
> }

von MeinerEiner (Gast)


Lesenswert?

Geht deswegen nicht, weil func2 nichts von dem lokalen Array weiss.
Es kenn nur seine Variablen und die globalen. Die lokalen Variablen 
einer anderen Funktion sieht es nicht.

Der lokale Array gilt also nur in func1.

von 12er Dude (Gast)


Lesenswert?

Hallo,

@ Bernd Hallinger
> Ein Arry als Rückgabe geht nicht. Du must der Funktion einen Zeiger auf
> das Array übergeben. Dann kannst du in der Funktion das Array verändern.
Nur zum richtigen Verständnis: Eine "Array"-Variable in "C" ist doch 
immer ein Zeiger (auf das erste Element).

In dem Quelltextauszug sind aber noch reilich Ungereimtheiten, so dass 
ich meine Zweifel habe, dass er sich überhaupt compilieren läßt, bzw. 
sinnvolle Ergebnisse liefert.

Stichworte: undefinierte/-deklarierte Variablen, Namensräume, 
Bereichsüberschreitungen, ...

Tschü Dude

von Peter D. (peda)


Lesenswert?

Bernd Hallinger wrote:
> Ein Arry als Rückgabe geht nicht.

Das geht schon, Du mußt Dir nur einen entsprechenden Typ definieren.

Bloß gewinnst Du dabei nichts, da das der Returnwert der Funktion ist, 
den Du einer gleichen Variable des Aufrufers zuweisen mußt.
Der Aufrufer muß sie also immer anlegen.


Peter

von Heinz B. (heinzb)


Lesenswert?

Arrays als rueckgabe wert geht schon.

Wenn Du das array mit call by reference uebergibst (pointer auf array)
dann kann die aufgrufene funktion da reinschreiben und der Aufrufer hat 
dann die Werte da wo er sie will.

Also auch als automatische variable (in der funktion deklariert)

Nur wenn ich mir das so anschaue was du da vorhast schlage ich vor das 
Du
eine strukur definierts da arrays ein paar nachteile haben.

Die dimension des arrays muss zwischen Aufrufer und Aufgerufenen 
abgesprochen sein oder man uebergibt das als zusaetzliche variable.

Also in etwa so:

//Defintions and Declaration:
typedef struct _mydata_s {
        unsigned short int    a;
        unsigned short int    b;
        unsigned short int    g;
} mydata_t;


// Function-Predefinitions:

mydata_t * func2( mydata_t *pD )
{
        unsigned char i=0;
  unsigned short int s_a = 20;
  unsigned short int s_b = 40;
  unsigned short int s_g = 60;
  pD->a = s_a*2;
  pD->a = s_b*2;
  pD->a = s_g*2;
// Das return st nicht notwendig da func2 ueber ptr pD direkt zugriff
// auf die daten hat
  return(pD);
}


void func1(void)
{
    mydata_t  loc_data;    // !!! nicht initialisiert
    func2( &loc_data );    // nach aufruf enthaelt
// loc_data.a  loc_data.b  loc_data.g die gwuenschten daten
    th_U = times[1];
    th_V = times[2];
    th_W = times[3];
}


//MAIN

int main(void)
{
  func1();
  return 0;
}

von 12er Dude (Gast)


Lesenswert?

Hallo,

@Heinz Blättner
> Wenn Du das array mit call by reference uebergibst (pointer auf array)...

Wie oben schon geschrieben:
Eine "Array"-Variable in "C" ist doch immer ein Zeiger (auf das erste 
Element).

Also kann man ein "Array" (nicht nur ein Element!) doch nur als Pointer 
übergeben.

Tschü Dude

von Bernd H. (bhallinger) Benutzerseite


Lesenswert?

Eben es ist schon ein Pointer aber man muss der Funktion die Adresse hin 
übergeben. Die Adresse / der Pointer muss der Funktuion bekannt gemacht 
werden nicht das Array zurückgeben.

void foo (unsigned int * liste)
{
liste[1] = 0;
liste[2} = 4711;
}


void main(void)
{
unsigned int Folge[10];

foo(Folge);

printf("%d", Folge[2]);
}

von Heinz B. (heinzb)


Lesenswert?

@ 12er Dude (Gast)
>> Wenn Du das array mit call by reference uebergibst (pointer auf array)...

> Wie oben schon geschrieben:
> Eine "Array"-Variable in "C" ist doch immer ein Zeiger (auf das erste Element).
IMMER nicht
siehe: 
http://en.wikipedia.org/wiki/C_(programming_language)#Array-pointer_interchangeability

> Also kann man ein "Array" (nicht nur ein Element!) doch nur als Pointer
> übergeben.
Das ist der default Fall
Mit etwas Aufwand kann man auch arrays by value uebergeben :-)
Es wird dann wie gewohnt eine Kopie auf dem stack erzeugt.

br heinz

von Heinz B. (heinzb)


Lesenswert?

Beispiel fuer array call by value:


struct Array {
     int element[100];
} a;

void foo( struct Array arr)
{
   arr.element[0] = 1;
}

int main(void)
{
    a.element[0] = 0;
    foo(a);
    return a.element[0];
}

main exist status wird 0 werden, da foo() eine Kopie des arrays bekommt,
damit wird a.element[0] nicht veraendert.

Das ist aber nicht empfehlenswert
  (da zusaetzlicher laufzeit fuer array kopieren anfaellt)
Besondert nicht auf embedded Kontrollern da:
- RAM ist nicht beliebig vorhanden (Platz fuer Kopie auf dem Stack)
- Laufzeit (fure das kopieren)

br heinz

von 12er Dude (Gast)


Lesenswert?

Hallo,

@Heinz Blättner
> en.wikipedia.org/wiki/C_(programming_langua...
Da steht doch genau das drin, was ich beschrieben habe. Welcher Teil 
widerspricht? (Bitte mal direkt gegenüberstellen)

>> Also kann man ein "Array" (nicht nur ein Element!) doch nur als Pointer
>> übergeben.
> Das ist der default Fall
> Mit etwas Aufwand...
Das hat dann aber nicht mehr viel mit Array-Parametern/-Rückgabewerten 
zu tun, sondern ist typunabhängig.

In Deinem Bsp. von heute 18:59 hast Du selbst gezeigt:
Array "Folge[]" ist zuweisungskompatibel zu Pointer (uint*) "liste".

Tschü Dude

von Heinz B. (heinzb)


Lesenswert?

@12er Dude (Gast)
>> en.wikipedia.org/wiki/C_(programming_langua...
>Da steht doch genau das drin, was ich beschrieben habe. Welcher Teil
>widerspricht? (Bitte mal direkt gegenüberstellen)
However, there is a distinction to be made between arrays and pointer 
variables. Even though the name of an array is in most expression 
contexts converted to a pointer (to its first element), this pointer 
does not itself occupy any storage. Consequently, you cannot change what 
an array "points to", and it is impossible to assign to an array.


>>> Also kann man ein "Array" (nicht nur ein Element!) doch nur als Pointer
>>> übergeben.
>> Das ist der default Fall
>> Mit etwas Aufwand...
>Das hat dann aber nicht mehr viel mit Array-Parametern/-Rückgabewerten
>zu tun, sondern ist typunabhängig.
typunabhängig ???

>In Deinem Bsp. von heute 18:59 hast Du selbst gezeigt:
>Array "Folge[]" ist zuweisungskompatibel zu Pointer (uint*) "liste".
Ist nicht von mir

von Sven P. (Gast)


Lesenswert?

12er Dude wrote:
> Wie oben schon geschrieben:
> Eine "Array"-Variable in "C" ist doch immer ein Zeiger (auf das erste
> Element).

Vorsichtig ausgedrückt:
NEIN NEIN UND NOCHMAL NEIN! :-)

Vektoren sind keine Zeiger!
1
int Vektor[100];
2
int *Zeiger_auf_Vektor = Vektor;
3
int **Zeiger_auf_Zeiger_auf_Vektor = &Zeiger_auf_Vektor;
4
5
int **Kein_Zeiger_auf_Zeiger_auf_Vektor = &Vektor;

http://www.lysator.liu.se/c/c-faq/c-2.html

von 12er Dude (Gast)


Lesenswert?

Hallo,

@ Sven P.
Schau Dir bitte den Verlauf des Thread und nicht nur die letzten 
Postings an. Zu klären ist, wie ein Array zurück-/übergeben wird.

Die von Dir gezeigten Zusammenhänge sind mir schon geläufig.
1
int Vektor[100];
2
int *Zeiger_auf_Vektor = Vektor;
3
// "Zeiger_auf_Vektor" zeigt nicht auf Vektor, sondern auf &(Vektor[0])
4
int *Zeiger_auf_Vektor = &Vektor;
5
// geht zur Not auch, bringt nichts, wie oben
"Vektor" ist (und bleibt) für den Compiler ein i m p l i z i t e r 
Zeiger, der aber selbst keine Adresse besitzt und daher nicht im 
Speicher zu finden ist. Also kann man seinen Wert nutzen/zuweisen 
(Adresse, auf die er zeigt), oder ihn derefernzieren.

Tschü Dude

von Karl H. (kbuchegg)


Lesenswert?

12er Dude wrote:

> "Vektor" ist (und bleibt) für den Compiler ein i m p l i z i t e r
> Zeiger, der aber selbst keine Adresse besitzt und daher nicht im
> Speicher zu finden ist. Also kann man seinen Wert nutzen/zuweisen
> (Adresse, auf die er zeigt), oder ihn derefernzieren.

Trotzdem solltest du vorsichtig sein mit der Aussage, dass ein Array ein 
Zeiger ist. Denn genau das ist es nicht. Ein Array ist ein Array. Ein 
Zeiger ist ein Zeiger. In manchen Fällen degeneriert ein Array zu einem 
Zeiger auf sein erster Element.
Aber ein Array ist KEIN Zeiger.

von Sven P. (Gast)


Lesenswert?

12er Dude wrote:
> Hallo,
>
> @ Sven P.
> Schau Dir bitte den Verlauf des Thread und nicht nur die letzten
> Postings an. Zu klären ist, wie ein Array zurück-/übergeben wird.
Schau Dir bitte den Verlauf des Threads an und nicht nur die letzten 
Postings. Dann fällt Dir nämlich auf, dass bereits die zweite Antwort 
hier von mir stammt und das Problem mit dem Codefetzen beschreibt.

Ist zwar keine Antwort auf dem Silbertablett, aber etwas Mitdenken darf 
man wohl erwarten. Zumal im Post vor mir schon eine mögliche und übliche 
Lösung gegeben wurde.

> Die von Dir gezeigten Zusammenhänge sind mir schon geläufig.
Sah aber nicht danach aus.

Ein Vektor ist und bleibt ein Vektor. Karl heinz Buchegger hat das 
richtig beschrieben.

von 12er Dude (Gast)


Lesenswert?


von Karl H. (kbuchegg)


Lesenswert?

12er Dude wrote:
> Hallo,
>
> ich bin nicht allein ;)
> 
http://books.google.de/books?id=vhOsStUNcnAC&pg=PA70&lpg=PA70&dq=impliziter+zeiger&source=bl&ots=63zHXg2MQm&sig=KlVoZDfX0nSwrtonZz9YRAFEkYA&hl=de&ei=hxfaScPTEJnU-Qab5MXMBQ&sa=X&oi=book_result&ct=result&resnum=4
>
> Und bitte das Wort "implizit" beachten.
>
> Tschü Dude

Ich nehme an du meinst den Satzteil "... Zeigerarray ist, wie bei 
anderen Arrays auch, ein impliziter Zeiger ..."

Nun, er ist dort genauso falsch wie bei dir.
Ein Array ist kein Zeiger. Noch nicht mal implizit.

Warum wir so darauf herumreiten?

Na dann erklär doch mal mit deinem impliziten Zeiger, wo denn hier das 
Problem liegt:

file1.c
*******
1
int Test[5];
2
3
int main()
4
{
5
  foo();
6
7
  printf( "%d\n", Test[2] );
8
}

file2.c
*******
1
extern int* Test;
2
3
void foo()
4
{
5
  Test[2] = 5;
6
}

Ein Array ist kein Zeiger und ein Zeiger ist kein Array.
Ein Array kann unter bestimmten Umständen zu einem Zeiger auf die 
Adresse des ersten Array-Elementes degenerieren. Aber: Das bedeutet 
nicht, dass es ein Zeiger IST! Die Umwandlung in die erste 
Elementadresse wird rein durch die Verwendung des Arrays ausgelöst und 
durch sonst gar nichts. Die Verwendung der Wörter 'Array', 'Zeiger' und 
'ist' in ein und demselben Satz ist zumindest problematisch bis oft 
einfach nur falsch. Im besten Fall ist es für den geneigten Leser 
einfach nur missverständlich oder verwirrend, so dass dieser Satz am 
Besten so nie gefallen wäre.

Mit dem gleichen Recht könnte ich auch sagen, dass ein int ein 
impliziter Zeiger ist, der nie irgendwo auftaucht. Denn natürlich führt 
der Compiler darüber Buch, wo im Speicher welche Variable liegt. In 
diesem Sinne ist praktisch alles ein 'impliziter Zeiger' (auch 
Funktionen). Das hilft aber niemandem weiter und erklärt nichts.

von 12er Dude (Gast)


Lesenswert?

Hallo Karl heinz Buchegger,

gut, dann beenden wir hier diese Haarspalterei. Auf einen grünen Zweig 
kommen wir wohl eh nicht.

Und sorry an den OP, dass wir seinen Thread missbraucht haben.

Tschü Dude

von Karl H. (kbuchegg)


Lesenswert?

12er Dude wrote:

> Und sorry an den OP, dass wir seinen Thread missbraucht haben.

Ich denke das ist kein Problem.

Alles worauf Sven und ich hinaus wollen ist:
Sei vorsichtig, was du einem Neueinsteiger erzählst. Ich hab schon 
mitgekriegt, dass du den Unterschied verinnerlicht hast und dass du 
Arrays und Zeiger nicht verwechselst. Aber ein Neueinsteiger hört 
'Array', 'Zeiger' und baut sich innerlich den Satz zusammen 'Ein Array 
ist ein Zeiger'. Dass du den Satz ganz anders gemeint hast, überhört er. 
Es bringt nichts, bei diesem Thema mit sprachlichen Feinheiten zu kommen 
und das Wesentliche in ein einziges Wort 'implizit' zu legen. Diese 
Botschaft kommt einfach nicht an.

Das hab ich oft genug auf comp.lang.c-c++ und Konsorten miterlebt. Bis 
wir uns dort in der Community darauf geeinigt haben, solche Sätze schon 
im Keim zu ersticken. Ab da lief es dann besser.

von name (Gast)


Lesenswert?

Feld gleich Zeiger?

was passt hier nicht:

[c]
void schmafu (void)
{
    int  test[2];
    int* ptest = test;
    int  nochntest[2];

    test++;
    ptest++;
    nochntest[]++;

    *test = 'a';
    *ptest = 'b';
    *(nochntest[]) = 'c';
    *(nochntest[0]) = 'c';
}

p.s.: als Anfänger hab ich sowohl Variante a als auch Variante b ohne 
Initialisierung des Zeigers probiert. b fand ich lustiger!
c hab ich noch nicht probiert, aber das wär doch die Umsetzung der 
Aussage Array == Pointer?

von Johnny Maxwell (Gast)


Lesenswert?

> gut, dann beenden wir hier diese Haarspalterei. Auf einen grünen Zweig
> kommen wir wohl eh nicht.

Der Unterschied ist doch ziemlich deutlich: Ein Pointerarray braucht 
noch ein zusaetzliches Wort im Speicher (eben fuer den Pointer) und ein 
Array nicht, weil dessen Adresse fest ist.

Ob 1 Wort (also z.B. 4 Bytes) jetzt weniger als ein Haar sind muss jeder 
selber wissen :)

Einen groesseren Unterschied macht das in der Adressierung: 
Pointerarrays werden indirekt adressiert, Arrays direkt.

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.