Forum: Compiler & IDEs Inline bei Call by Reference


von Frank (Gast)


Lesenswert?

Hallo,

ich möchte eine generische Funktion mit dem Zusatz Inline 
implementieren, diese Funktion soll den Zugriff auf ein Array ausführen. 
Jetzt Frage ich mich, wie der Compiler den Code ersetzt. Muss ich den 
Übergabeparameter als Call by Reference durchführen ( müsste dann auf 
NULL Pointer prüfen) oder geht auch Call by Value. Die Struktur hätte 
diese Form:

struct array
{
   struct liste* data;  /* pointer aufs erste elment vom Array*/
   char anzahl_data_elemente;
   char max_anzahl_data_elemente;
}

inline void ArrayZugriff( struct array* container, char element_id, 
struct  list* rueckgabewert)
{
   if( element_id < max_anzahl_data_elemente)
        rueckgabewert = container->data[element_id];
}

main()
{
   .
   .
   .
   ArrayZugriff( &container, element_id, &rueckgabewert)

}

von Oliver S. (oliverso)


Lesenswert?

Ich sach mal so:

Da der gcc vom Programmierer vorgeschlagenes inlining schlicht 
ignoriert, und einfach dann inlined, wenn er das selber für richtig 
hält, ist die Frage zwar interessant, aber ansonsten belanglos.

Und müssen musst du gar nichts.

Bleibt noch die Frage, was du gegen Funktionen hast, die ihr Ergebnis 
per Return zurückgeben.

Oliver

von Karl H. (kbuchegg)


Lesenswert?

Frank schrieb:
> Hallo,
>
> ich möchte eine generische Funktion mit dem Zusatz Inline
> implementieren, diese Funktion soll den Zugriff auf ein Array ausführen.
> Jetzt Frage ich mich, wie der Compiler den Code ersetzt. Muss ich den
> Übergabeparameter als Call by Reference durchführen ( müsste dann auf
> NULL Pointer prüfen) oder geht auch Call by Value.

call bei value ist ok.
stell dir einfach den Code an der Aufrufstelle eingesetzt vor und dann 
optimierst du selber mal daran rum. Du wirst sehen, das ist nicht 
schwer, die Argumente los zu werden.
Wenn du das auf dem Papier in 30 Sekunden kannst, dann kann das dein 
Compiler schon lange.

Das allerdings
1
inline void ArrayZugriff( struct array* container, char element_id, struct list* rueckgabewert) {
2
if( element_id < max_anzahl_data_elemente)
3
rueckgabewert = container->data[element_id];
4
}
ist keine so gute Idee. Was hast du gegen Returnwerte?
Dann hätte dich nämlich der Compiler auch darauf aufmerksam gemacht, 
dass du auch im Fehlerfall einen Returnwert brauchst.

von Frank (Gast)


Lesenswert?

Wie würdest du es machen
@Karl Heinz

von Karl H. (kbuchegg)


Lesenswert?

Frank schrieb:
> Wie würdest du es machen
> @Karl Heinz

erst mal musst du eine Strategie ausgeben, welcher Wert geliefert werden 
soll, bzw. was passieren soll, wenn der Index tatsächlich zu groß ist.

Einen Fehler abzufangen ist gut. Aber der Aufrufer der Funktion weiß 
nichts davon, dass da ein Fehler abgefangen wurde und er daher mit dem 
gelieferten nichts anfangen kann. Wie ist dann in so einem Fall weiter 
zu verfahren?

von Frank (Gast)


Lesenswert?

Hi,

wenn mit einem falschen index zugegriffen wird... Soll es ein Default 
wert zurückliefen.
Fur mich ist eigentlich von Interesse, ob man die Übergabeparameter und 
der Return wert als Call by Value übergeben kann.
Hintergrund... Eine Funktion soll über c files hinweg verwendet werden 
und als Get funktion Daten liefern. Dabei kann es vorkommen, das diese 
Get Funktion 2000mal aufgerufen wird und somit ein Inline von Vorteil 
wäre. ( Lauzeit)

von Rolf Magnus (Gast)


Lesenswert?

Frank schrieb:
> Fur mich ist eigentlich von Interesse, ob man die Übergabeparameter und
> der Return wert als Call by Value übergeben kann.

Warum sollte man das nicht können?

von Oliver (Gast)


Lesenswert?

Wobei die Übergabeart eines "Return-Wertes als Parameter" zu den 
absoluten C-Basics gehört. Da wäre jetzt dann doch mal ein C-Buch 
angebracht.

Oliver

von Ralf G. (ralg)


Lesenswert?

Frank schrieb:
> Fur mich ist eigentlich von Interesse, ob man die Übergabeparameter und
> der Return wert als Call by Value übergeben kann.

Rolf Magnus schrieb:
> Warum sollte man das nicht können?

Also mir raucht da der Schädel:
 Return-Wert (=Rückgabe) übergeben? Als Wert? Was kommt denn da wie 
zurück?

Die Billigvariante um ein Element aus einem Array zu erhalten, geht doch 
so:
1
x = a[i];

Meiner Meinung sollte sich an dem 'Aussehen' durch die Verwendung einer 
Funktion nicht viel ändern.
1
x = f(a[i], /*weitere Parameter */);

PS: Wenn's uuunbedingt 'inline' sein muss und es nur um die Indexprüfung 
geht, würde ich mal den Begriff 'Makro' in den Raum werfen.

von Rolf Magnus (Gast)


Lesenswert?

Ralf G. schrieb:
> Rolf Magnus schrieb:
>> Warum sollte man das nicht können?
>
> Also mir raucht da der Schädel:
>  Return-Wert (=Rückgabe) übergeben? Als Wert? Was kommt denn da wie
> zurück?

Na der Wert eben. Wo ist das Problem?

> Die Billigvariante um ein Element aus einem Array zu erhalten, geht doch
> so:x = a[i];
>
> Meiner Meinung sollte sich an dem 'Aussehen' durch die Verwendung einer
> Funktion nicht viel ändern.x = f(a[i], /*weitere Parameter */);

Was er machen will, scheint eher sowas zu sein:
1
x = p->a[i];
und daraus soll ein:
1
x = f(p, i);
werden.

> PS: Wenn's uuunbedingt 'inline' sein muss und es nur um die Indexprüfung
> geht, würde ich mal den Begriff 'Makro' in den Raum werfen.

Ein Makro hat hier allerings keinerlei Vorteile gegenüber einer 
inline-Funktion, bringt dafür aber die üblichen zusätzlichen Gefahren 
mit sich.

von Karl H. (kbuchegg)


Lesenswert?

Frank schrieb:
> Hi,
>
> wenn mit einem falschen index zugegriffen wird... Soll es ein Default
> wert zurückliefen.

Gut.

Wo liegt dann das Problem bei
1
inline struct list ArrayZugriff( struct array* container, char element_id ) __attribute__((always_inline))
2
{
3
  if( element_id < container-> anzahl_data_elemente)
4
    return container->data[element_id];
5
6
  return defaultValue;
7
}

das präsentierst du dem Compiler so, dass er inlinen kann, und überlässt 
den Rest dem Compiler.

von Ralf G. (ralg)


Lesenswert?

Rolf Magnus schrieb:
> scheint eher sowas

eben ;-)

[nebenbei]
Rolf Magnus schrieb:
> Na der Wert eben. Wo ist das Problem?

Irgendwas habe ich da wohl falsch verstanden:
1
void f(int x)
2
{
3
  x = 42;
4
};
5
// ...
6
int y = 12;
7
f(y);
8
// ...
Das wäre für mich jetzt die Übergabe als Wert. Da sehe ich nichts 
zurückkommen.
[/nebenbei]

von Karl H. (kbuchegg)


Lesenswert?

Ralf G. schrieb:

>> Na der Wert eben. Wo ist das Problem?
>
> Irgendwas habe ich da wohl falsch verstanden:
>
1
> void f(int x)
2
> {
3
>   x = 42;
4
> };
5
> // ...
6
> int y = 12;
7
> f(y);
8
> // ...
9
>
> Das wäre für mich jetzt die Übergabe als Wert. Da sehe ich nichts
> zurückkommen.

1
int f( int x )
2
{
3
  return 2*x;
4
}
5
6
int main()
7
{
8
  int y;
9
10
  y = f( 5 );
11
}

von Ralf G. (ralg)


Lesenswert?

@Karl Heinz
Ja klar! Aber gegen so einen Rückgabewert sträubt sich Frank doch. Der 
soll doch 'oben' wieder rauskommen.

Oder:
Ralf G. schrieb:
> Irgendwas habe ich da wohl falsch verstanden:

von Rolf Magnus (Gast)


Lesenswert?

Ralf G. schrieb:
> Rolf Magnus schrieb:
>> Na der Wert eben. Wo ist das Problem?
>
> Irgendwas habe ich da wohl falsch verstanden:
> void f(int x)
> {
>   x = 42;
> };
> // ...
> int y = 12;
> f(y);
> // ...
> Das wäre für mich jetzt die Übergabe als Wert.

Richtig.

> Da sehe ich nichts zurückkommen.

Warum sollte es? Du übergibst ja per Wert. Du verwechselst vielleicht 
Wert mit Objekt. 12 ist z.B. ein Wert. Einen Wert kann man nicht ändern. 
Ich kann z.B. nicht sagen, 12 soll jetzt 42 sein. Man kann nur in eine 
Variable einen anderen Wert schreiben. Ich kann also sagen, x soll jetzt 
den Wert 42 enthalten. x ist aber ein anderes Objekt als y. Daher wird 
sich y nicht auf magische Weise ändern, nur weil man x ändert.
Wenn du stattdessen "by-reference" übergibst, ist y eine Referenz auf x, 
wodurch sich die Änderungen an y auch entsprechend auf x auswirken.

von Ralf G. (ralg)


Lesenswert?

Rolf Magnus schrieb:
> Warum sollte es? Du übergibst ja per Wert.
Das ist mir alles klar.

Frank schrieb:
> Muss ich den
> Übergabeparameter als Call by Reference durchführen ( müsste dann auf
> NULL Pointer prüfen) oder geht auch Call by Value.

Karl Heinz schrieb:
> call bei value ist ok.

Ich werde nur aus diesen beiden Aussagen nicht ganz schlau, denn

Ralf G. schrieb:
> Irgendwas habe ich da wohl falsch verstanden:
bzw. interpretiere in den Eröffnungspost was falsches hinein.

von Axel S. (a-za-z0-9)


Lesenswert?

Ralf G. schrieb:
>> Irgendwas habe ich da wohl falsch verstanden:
> bzw. interpretiere in den Eröffnungspost was falsches hinein.

Der TE hat zwei Probleme.

1. er sträubt sich gegen einen Returnwert und macht lieber call-by-(non 
const)-reference. Das ist im wesentlichen eine Geschmacksfrage.

2. er glaubt, die Signatur seiner Funktion, insbesondere die Frage ob er 
call-by-value oder call-by-reference verwendet, hätte irgendwas mit der 
inline-barkeit zu tun. Hat es nicht.

Wenn der Compiler eine Funktion inlined, dann bleibt die Semantik 
komplett erhalten. Und die Details der Parameter/Returnwertübergabe 
verlieren jegliche Bedeutung. Wie denn auch sonst?


XL

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Frank schrieb:
> Hallo,
>
> ich möchte eine generische Funktion mit dem Zusatz Inline
> implementieren, [...]

Ob inline oder nicht spielt keine Rolle für die Semantik (Bedeutung) 
des Codes.  Es hat bestenfalls Auswirkungen auf Ausführungszeit und 
Speicherplatz.

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.