Forum: Mikrocontroller und Digitale Elektronik call-by-reference, mit Zeiger und Referenzen


von Sepp (Gast)


Lesenswert?

Hallo, es gibt ua. 2 Möglichkeiten, einen call by reference zu nutzen.

void func(int& argA);
Aufruf: func(var);

void func(int* argB);
Aufruf: func(&var);

Worin liegt hier der Untschied/Vorteil?

von Nase (Gast)


Lesenswert?

Sepp schrieb:
> Worin liegt hier der Untschied/Vorteil?
Ja.

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Sepp schrieb:
> Worin liegt hier der Untschied/Vorteil?

C kennt keine Referenzen und also nur die Pointervariante. In C++ lässt 
sich mit der Referenzvariante kein Nullpointer übergeben (und 
auswerten).

In der Zeile des Aufrufs sieht man nur bei der Pointervariante, daß 
hier ein call-by-reference stattfindet, die Referenzvariante ist optisch 
nicht vom call-by-value zu unterscheiden. Hier ist also zwingend der 
Funktionsprototyp zu betrachten.


Hat also beides sein für und wider.

von SK (Gast)


Lesenswert?

Die erste Variante funktioniert meines wissens nach nur in C++, und die 
zweite halt auch in C. In einen C-Programm läßt sich die erste Variante 
nicht Compilieren.

von Leo B. (luigi)


Lesenswert?

Also ich bin zwar kein Guru, aber meines Wissens nach ist der wirklich 
gravierende Unterschied tatsächlich nur, dass ein call-by-reference 
immer ein gültiges Objekt als Wert übergeben bekommt. Man kann also im 
Code ohne vorherige Prüfung darauf zugreifen.
Bei einem call-by-value mit einem Pointer ist ein NULL-Pointer ebenfalls 
möglich und es muss daher vor dem Zugriff auf das Objekt der Pointer 
überprüft werden.
Ansonsten ist mir allerdings auch noch kein wesentlicher Unterschied 
aufgefallen.

von Klaus W. (mfgkw)


Lesenswert?

Leo B. schrieb:
> Ansonsten ist mir allerdings auch noch kein wesentlicher Unterschied
> aufgefallen.

Einen Zeiger kann man ändern, also auf etwas anderes zeigen lassen. Bei 
einer Referenz geht das nicht.

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Klaus Wachtler schrieb:
> Einen Zeiger kann man ändern, also auf etwas anderes zeigen lassen. Bei
> einer Referenz geht das nicht.

Das bezieht sich auf die Behandlung innerhalb der Funktion, der der 
Zeiger bzw. die Referenz umgeben wurde. Das Verändern des Zeigers in der 
Funktion wirkt sich nicht auf den Zeiger des Aufrufers aus -- denn, wie 
Leo sehr schön formuliert hat, handelt es sich bei der Zeigerübergabe 
tatsächlich um einen call-by-value.

von Rolf M. (rmagnus)


Lesenswert?

Klaus Wachtler schrieb:
> Leo B. schrieb:
>> Ansonsten ist mir allerdings auch noch kein wesentlicher Unterschied
>> aufgefallen.
>
> Einen Zeiger kann man ändern, also auf etwas anderes zeigen lassen. Bei
> einer Referenz geht das nicht.

Das ist eher aus der Sicht der typischen Implementation in Compilern 
geschrieben. Aus Sicht der Abstraktion in C++ ist eine Referenz nur ein 
neuer Name für ein bereits bestehendes Objekt. In dieser Denkweise 
ergibt es gar keinen Sinn, davon zu sprechen, ob man sie auf ein anderes 
Objekt "zeigen lassen" (oder von mir aus verweisen lassen) kann, da sie 
im Prinzip selbst das Objekt ist.

SK schrieb:
> meines wissens nach

Leo B. schrieb:
> meines Wissens nach

Eigentlich sage ich zu sowas normalerweise nichts, aber da ich es in 
letzter Zeit so häufig lese, kann ich doch nicht still sein. Es heißt 
entweder "meinem Wissen nach" oder "meines Wissens", aber nie "meines 
Wissens nach".

von Klaus W. (mfgkw)


Lesenswert?

Rolf Magnus schrieb:
> Klaus Wachtler schrieb:
>> Leo B. schrieb:
>>> Ansonsten ist mir allerdings auch noch kein wesentlicher Unterschied
>>> aufgefallen.
>>
>> Einen Zeiger kann man ändern, also auf etwas anderes zeigen lassen. Bei
>> einer Referenz geht das nicht.
>
> Das ist eher aus der Sicht der typischen Implementation in Compilern
> geschrieben. Aus Sicht der Abstraktion in C++ ist eine Referenz nur ein
> neuer Name für ein bereits bestehendes Objekt. In dieser Denkweise
> ergibt es gar keinen Sinn, davon zu sprechen, ob man sie auf ein anderes
> Objekt "zeigen lassen" (oder von mir aus verweisen lassen) kann, da sie
> im Prinzip selbst das Objekt ist.

Naja, und  genau das gilt nicht, wenn man einen Zeiger auf ein Objekt 
hat.
Damit hat man einen deutlichen Unterschied zwischen Zeiger und Referenz 
neben der Möglichkeit des ungültigen Zeigers (NULL).

von Theoretiker (Gast)


Lesenswert?

Rufus Τ. Firefly schrieb:
> In C++ lässt
> sich mit der Referenzvariante kein Nullpointer übergeben

Oh, doch:
1
int f(int& a)
2
{
3
  return a + 123;
4
}
5
6
int main()
7
{
8
  int* ptr = 0;
9
  return f(*ptr);
10
}

Übrigens, keine Warnung mit gcc -Wall -O2...

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Igitt. Das ist ... eklig.

von Rolf M. (rmagnus)


Lesenswert?

Theoretiker schrieb:
> Rufus Τ. Firefly schrieb:
>> In C++ lässt
>> sich mit der Referenzvariante kein Nullpointer übergeben
>
> Oh, doch:

Nicht, ohne davor undefiniertes Verhalten auszulösen.

> int f(int& a)
> {
>   return a + 123;
> }
>
> int main()
> {
>   int* ptr = 0;
>   return f(*ptr);

An dieser Stelle dereferenzierst du ptr, was du nicht darfst, da es ein 
Nullzeiger ist. Das Verhalten ist aber der Stelle (nicht erst innerhalb 
von f, sondern bereits beim *ptr) undefiniert. Die Referenz kommt da 
noch gar nicht ins Spiel. Das ist quasi vergleichbar damit, wenn du 
einfach
1
   return *ptr;
geschrieben hättest.

> }
>
> Übrigens, keine Warnung mit gcc -Wall -O2...

Das ist allerdings erstaunlich, denn gerade mit -O2 hätte ich erwartet, 
dass er die Variable ptr wegoptimiert und dann bei der Dereferenzierung 
merkt, dass das ein Nullzeiger ist.

von Theoretiker (Gast)


Lesenswert?

Mein Beispiel ist ein triviales.

Es ging um die Behauptung, Referenzen würden vor Null-Pointer etc. 
schützen und immer korrekt sein. Und genau das tun sie eben nicht. Es 
ist überhaupt kein Problem, ungültige Referenzen zu erzeugen und sie 
tief ins System, z.B. in Konstruktoren zu verschleppen. Der 
Zugriffsfehler kann dann an völlig unerwarteter Stelle und zeitlich 
völlig unkorreliert auftreten. Und genau das ist das Problem.

Man muss sich immer im klaren sein: Eine Referenz ist nichts anderes als 
syntaktisch Zucker für einen Pointer den man nicht auf Null testen kann.

Illegale Referenzen sorgen für richtig Ärger in komplexen Systemen.

von Klaus W. (mfgkw)


Lesenswert?

Theoretiker schrieb:
> Mein Beispiel ist ein triviales.

Aber kein gültiges.
Daß ein Compiler es nicht anmeckert, heißt noch lange nicht daß es 
gültiges C wäre.

Theoretiker schrieb:
> Illegale Referenzen sorgen für richtig Ärger in komplexen Systemen.

ach, hat jemand das Gegenteil behauptet?

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.