Forum: Mikrocontroller und Digitale Elektronik Kann eine Funktion 2 Werte zurückgeben per Return?


von Msp 4. (msp430_crew)


Lesenswert?

Ich dachte an soetwas:
int test(void)
{foo;
return a,b;
}

Wie kann man das machen?

von Jens D. (jens) Benutzerseite


Lesenswert?

Jein
nicht direkt.
Du kannst aber einen Pointer der funktion übergeben in der du 2 werte 
aenderst.

http://www.mikrocontroller.net/articles/AT91-TWI#twi_read

Schau dir das hier mal an

von Läubi .. (laeubi) Benutzerseite


Lesenswert?

nein.
Eine Funktion hat per definition nur EINEN Rückgabewert.
Du kannst aber einen struct z.B. verwenden, oder der Funktion pointer 
übergeben wo sie die Ergebnisse hinschreiben soll.

von Msp 4. (msp430_crew)


Lesenswert?

Danke!

von Mark S. (struberg)


Lesenswert?

Einfach den 2. Wert per call-by-reference übergeben


int wert2;

int testfn(int* pwert2) {
  *pwert2 = A;
  return B;
}

von Philipp Karbach (Gast)


Lesenswert?

du kannst aber auch shiften, das machte man früher wenn man wenig 
speicher hatte gerne:

int dostuff(int r,int g,int b,int i)
{
int value = r | ( g << 8 ) | ( b << 16 ) | ( i << 24 );

return value;
}

die werte lassen sich dann wie folgt auseinander nehmen:

int color = dostuff(128,96,28,255);
int r = color & 255;
int g = ( color >> 8 ) & 255;
int b = ( color >> 16 ) & 255;
int i = ( color >> 24 ) & 255;

So habe ich früher gerne mal farben "kodiert" :). auch eine möglichkeit!

von Dirk S. (tomcat)


Lesenswert?

Das mit der Struct als Returnwert hört sich unheimlich an.
Legt der Compiler die Struktur vor Funktionsaufruf bereits auf dem Stack 
an?
Wie kann man die einzelnen Elemente dann erreichen?
Wird von der Funktion ein Zeiger zurückgegeben?
Wie funktioniert das genau, weis das einer?

von Karl H. (kbuchegg)


Lesenswert?

1
#include <stdio.h>
2
3
struct Pair {
4
  int Component1;
5
  int Component2;
6
};
7
8
9
struct Pair foo( void )
10
{
11
  struct Pair RetVal;
12
13
  RetVal.Component1 = 5;
14
  RetVal.Component2 = 7;
15
16
  return RetVal;
17
}
18
19
int main()
20
{
21
  struct Pair Result;
22
23
  Result = foo();
24
25
  printf( "%d %d\n", Result.Component1, Result.Component2 );
26
}

> Legt der Compiler die Struktur vor Funktionsaufruf bereits auf
> dem Stack an?

Könnte er. Ist aber dem Compiler überlassen.

> Wie kann man die einzelnen Elemente dann erreichen?
So wie bei jeder anderen struct auch: Indem man die Komponente
angibt, auf die man zugreifen möchte

> Wird von der Funktion ein Zeiger zurückgegeben?
Nein. Im Funktionskopf steht, dass eine Struktur zurückgegeben
wird. Und genau das passiert auch. Zumindest dann, wenn der
Compiler keine Return-Value-Optimization macht.

> Wie funktioniert das genau, weis das einer?
Ja, dein Compiler.

von Dirk S. (tomcat)


Lesenswert?

Vom Aufbau her hätte ich mir das auch genau so vorgestellt.
Sieht allerdings nach einer ziehmlichen Kopierorgie aus.
Das lokale struct RetVal nuss ja bei return irgendwohin kopiert werden, 
wo es den Funktionsaufruf "überlebt". Und als zweites das kopieren in 
die Variable "Result" damit man auf die einzelnen Elemente Zugriff 
bekommt. Kann da der Kompiler überhaupt optimieren? Schließlich kann die 
Funktion von verschiedenen Stellen aus aufgerufen werden und die 
"Returnstruct" (woimmer sie auch liegen mag) muss damit Standardisiert 
sein.

von Karl H. (kbuchegg)


Lesenswert?

Dirk S. wrote:
> Kann da der Kompiler überhaupt optimieren?

Und wie er das kann!
C++ lebt davon, dass es hier eine Möglichkeit zur Optimierung
gibt.

> Schließlich kann die
> Funktion von verschiedenen Stellen aus aufgerufen werden und die
> "Returnstruct" (woimmer sie auch liegen mag) muss damit Standardisiert
> sein.

Und?
Wenn der Compiler die NRVO (named return value optimization)
immer benutzt, ist das ja kein Problem.

Was ist die NRVO?
Kurz gesagt, der Compiler stellt das hier:
1
struct Pair foo( void )
2
{
3
  struct Pair RetVal;
4
5
  RetVal.Component1 = 5;
6
  RetVal.Component2 = 7;
7
8
  return RetVal;
9
}
10
11
int main()
12
{
13
  struct Pair Result;
14
  Result = foo();

so um
1
void foo( struct Pair* pTmp )
2
{
3
  pTmp->Component1 = 5;
4
  pTmp->Component2 = 7;
5
}
6
7
int main()
8
{
9
  struct Pair Result;
10
11
  foo(&Result);

et voila, keine Kopierorgie mehr.

von Dirk S. (tomcat)


Lesenswert?

Danke, sehr anschaulich erklärt.

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.