Du bist nicht angemeldet.

Stilllegung des Forums
Das Forum wurde am 05.06.2023 nach über 20 Jahren stillgelegt (weitere Informationen und ein kleiner Rückblick).
Registrierungen, Anmeldungen und Postings sind nicht mehr möglich. Öffentliche Inhalte sind weiterhin zugänglich.
Das Team von spieleprogrammierer.de bedankt sich bei der Community für die vielen schönen Jahre.
Wenn du eine deutschsprachige Spieleentwickler-Community suchst, schau doch mal im Discord und auf ZFX vorbei!

Werbeanzeige

simbad

unregistriert

21

13.04.2013, 12:29

Pre-Post:
Ich sehe es nicht ein. Und es ist sarkastisch gemeint. Aber ich habe keine Lust die Diskussion weiterzuführen.

Post-Post:
Ja ich sehe es ein. Ich habe 30 Jahre lang in einem kontinuierlichen Wahnzustand gelebt und gearbeitet und dabei eines der entscheidenden Konzepte der Programmiersprache C völlig falsch verstanden. Ich bedanke mich für die Gnade der Erleuchtung und werde nie wieder solchen Unfug verbreiten.

simbad

unregistriert

22

13.04.2013, 12:42

Aus dem ANSI Standard:

... Except when it is the operand of the sizeof operator or the unary & operator, or is a
string literal used to initialize an array, an expression that has type ‘‘array of type’’ is
converted to an expression with type ‘‘pointer to type’’ that points to the initial element of
the array object and is not an lvalue. If the array object has register storage class, the
behavior is undefined.
...

Der Name der Variablen eines Arrays wird, sobald es in eine Ausdruck verwendet wird, und dazu zählen auch Funktionsaufrufe, in einen Pointer auf das erste Element des Arrays umgewandelt.
"Implizit Type Conversion"

Mit Ausnahme von sizeof(), weshalb ein vergleich mit dem Verhalten von sizeof(), unangemessen ist. Ich habe recht.
Dein Hinweis das, der Compiler das ganze ja in ein Register packen könnte zieht auch nicht, weil letzter absatz gilt.. "the behavior is undefined"

Aber ich habe unrecht. Und du hast weiterhin recht.
Alles Müll was ich hier zitiere.

BlueCobold

Community-Fossil

Beiträge: 10 738

Beruf: Teamleiter Mobile Applikationen & Senior Software Engineer

  • Private Nachricht senden

23

13.04.2013, 12:53

Aber ich habe keine Lust die Diskussion weiterzuführen
Offenbar nicht. Wäre aber besser gewesen. Du hast Dir nämlich trotz Deines Zitats nicht mehr Recht verschafft als vorher, auch wenn Du das anders siehst. Spannend finde ich in diesem Zusammenhang z.B. wie Du den Teil mit dem String-Literal gekonnt ignorierst.
Du darfst nun gern wieder mehrere Posts nacheinander schreiben oder Du darfst ausnahmsweise auch mal die Edit-Funktion benutzen. :) Vielleicht hast Du ja mit mehreren Posts aber auch einfach nur mehr Recht, wer weiß.
Teamleiter von Rickety Racquet (ehemals das "Foren-Projekt") und von Marble Theory

Willkommen auf SPPRO, auch dir wird man zu Unity oder zur Unreal-Engine raten, ganz bestimmt.[/Sarkasmus]

24

13.04.2013, 13:00

Nachdem die lange Diskussion scheinbar ein Ende gefunden hat ( bzw. so langsam ) würde ich gerne wissen wofür man denn Zeiger auf Zeiger auf Datentyp braucht?
Ich sehe keinen Zweck darin, einen Zeiger auf einen anderen Zeiger zeigen zu lassen.

BlueCobold

Community-Fossil

Beiträge: 10 738

Beruf: Teamleiter Mobile Applikationen & Senior Software Engineer

  • Private Nachricht senden

25

13.04.2013, 13:04

Stell Dir vor Du hast einen Pointer und diesem soll dynamisch ein neuer Inhalt zugewiesen werden. Nun soll diese Zuweisung aber in einer Funktion geschehen indem der Zeiger durch Call by Reference übergeben wird. Du willst ihn quasi als Parameter an eine Funktion übergeben und er soll in der Funktion einen neuen Wert erhalten. Das geht natürlich nicht, indem Du ihn einfach übergibst, da sich der Pointer ja nur innerhalb der Funktion ändern würde. Damit er sich auch außerhalb ändert, übergibst Du eine Referenz darauf. Aus alten Tagen üblich ist ein Pointer darauf. Dafür ist Pointer auf Pointer sinnvoll, auch wenn ich immer eine Referenz auf einen Pointer vorziehen würde.

Beispiel:

C-/C++-Quelltext

1
2
3
4
int GetClosestPairOfEnemies ( Enemy** e1, Enemy** e2 );

Enemy *attacker, *defender;
int distance = GetClosestPairOfEnemies ( &attacker, &defender );

Damit bekommst Du Abstand beider Gegner und sogar Pointer auf die Gegner selbst. Rein fiktives Beispiel natürlich.

In anderen Sprachen lässt sich das etwas hübscher und klarer ausdrücken. In C# z.B:

C#-Quelltext

1
int GetClosestPairOfEnemies ( out Enemy e1, out Enemy e2 );


Verwendet wird sowas öfter in externen Komponenten, welche ihre Ressourcen nur durch solche Wege selbst erzeugen und dem Benutzer einen Pointer darauf zurückliefern. Hübsch ist es nicht sonderlich, aber durchaus nützlich, wenn auch wie gesagt Referenzen auf Pointer hier mMn hübscher wären.
Teamleiter von Rickety Racquet (ehemals das "Foren-Projekt") und von Marble Theory

Willkommen auf SPPRO, auch dir wird man zu Unity oder zur Unreal-Engine raten, ganz bestimmt.[/Sarkasmus]

Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von »BlueCobold« (13.04.2013, 13:11)


Schorsch

Supermoderator

Beiträge: 5 145

Wohnort: Wickede

Beruf: Softwareentwickler

  • Private Nachricht senden

26

13.04.2013, 14:12

Ich finde wenn die Diskussion weiter geführt wird, sollte man absplitten.
@ Teizakk: BlueCobold hat die Frage ja noch mal recht gut erklärt. Ansonsten wurde darauf auf Seite 1 schon mehrfach eingegangen;) Erst lesen, dann schreiben.
„Es ist doch so. Zwei und zwei macht irgendwas, und vier und vier macht irgendwas. Leider nicht dasselbe, dann wär's leicht.
Das ist aber auch schon höhere Mathematik.“

TGGC

1x Rätselkönig

Beiträge: 1 799

Beruf: Software Entwickler

  • Private Nachricht senden

27

13.04.2013, 15:48

Nachdem die lange Diskussion scheinbar ein Ende gefunden hat ( bzw. so langsam ) würde ich gerne wissen wofür man denn Zeiger auf Zeiger auf Datentyp braucht?
Ich sehe keinen Zweck darin, einen Zeiger auf einen anderen Zeiger zeigen zu lassen.
Hast du den von mir verlinkten Beitrag gelesen?

Except when it is the operand of the sizeof operator or the unary & operator, or is a string literal used to initialize an array, an expression that has type ‘‘array of type’’ is converted to an expression with type ‘‘pointer to type’’ that points to the initial element of the array object and is not an lvalue
Danke, das du den Ausschnitt aus dem Standard rausgesucht hast, der dir Richtigkeit meiner Aussage bestaetigt:
Zwischen text und moretext gibt es keinen grossen Unterschied. Beide sind bei fast allen Anwendungen erstmal einfach die Zahl einer Speicherstelle. Eine Ausnahme ist z.b. sizeof,

Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von »TGGC« (13.04.2013, 15:57)


TGGC

1x Rätselkönig

Beiträge: 1 799

Beruf: Software Entwickler

  • Private Nachricht senden

28

13.04.2013, 16:01

Der Compiler kann nicht warnen, wenn die Variable in einem anderen Modul anders importiert wird.
Hab ich was von Compiler gesagt?

Ausgabe von VS2010 zu deinem Testprogramm:

Quellcode

1
2
3
1>LINK : warning C4742: 'char * text' has different alignment in 'E:\programmierung\TestApp_Console\TestApp_Console\TestApp_Console.cpp' and 'E:\programmierung\TestApp_Console\TestApp_Console\test.cpp': 1 and 4
1>LINK : warning C4743: 'char * text' has different size in 'E:\programmierung\TestApp_Console\TestApp_Console\TestApp_Console.cpp' and 'E:\programmierung\TestApp_Console\TestApp_Console\test.cpp': 6 and 4 bytes
1>LINK : warning C4744: 'char * text' has different type in 'E:\programmierung\TestApp_Console\TestApp_Console\TestApp_Console.cpp' and 'E:\programmierung\TestApp_Console\TestApp_Console\test.cpp': 'array (6 bytes)' and 'pointer'

29

13.04.2013, 16:14

Deinen Beitrag habe ich durchgelesen, jedoch versteh ich nicht wie void ein ganz normaler Datentyp sein kann. Ich dachte immer es sei nur für Funktionen wichtig, um ihnen zu sagen, dass es keinen Rückgabewert gibt. Jedoch sagst du dort:

Zitat

Betrachten wir 73824 als Datum vom Typ int, dann ist 90008 also ein
int*, naemlich die Speicherstelle eines ints. Betrachten wir 73824 aber
wie hier als als void*, so ist 90008 also ein (void*)* kurz void**.
90008 ist nun also ein Pointer auf einen Pointer, also ein void**, die
Speicherstelle an der eine weiter Speicherstelle abgelegt ist.
Wie ist es möglich, dass man eine Zahl als void betrachten kann. Dann hätte diese Zahl ja garkeinen Datentypen und der Computer wüsste nicht was das nun sein soll oder? :S

Und ich habe mir das Beispiel von BlueCobold jetzt mal etwas länger angeguckt und ein kleines Programm dazu geschrieben.

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
#include <iostream>

using namespace std;

class Enemy
{
public:
    Enemy();
    int xPos;
    int yPos;
    int Funktion();
};

Enemy::Enemy()
{
    xPos = 200;
    yPos = 400;
}

int Enemy::Funktion()
{
    return 0;
}

int GetClosestPairOfEnemies ( Enemy **e1, Enemy **e2 );

int main()
{
    Enemy *attacker = new Enemy, *defender = new Enemy;
    int Distance;

    Distance = GetClosestPairOfEnemies ( &attacker, &defender );

    delete attacker;
    attacker = NULL;

    delete defender;
    defender = NULL;

    return 0;
}

int GetClosestPairOfEnemies ( Enemy **e1, Enemy **e2 )
{
    /*
    ... Berechnungen ...
    */

    return 0;
}


Es ist nichts großes oder besonderes, aber ich dachte es könnte mir beim Verstehen helfen. In diesem Beispiel werden die Adressen der Instanzen Enemy *attacker = new Enemy und Enemy *defender = new Enemy an die beiden Instanzen **e1 und **e2 übergeben. Möchte ich jedoch in der Funktion GetClosestPairOfEnemies in die Klasse "hinein greifen" so erlaubt mir der Compiler dies nicht. Schreibe ich jetzt z.B.:

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
int GetClosestPairOfEnemies ( Enemy **e1, Enemy **e2 )
{
    /*
    ... Berechnungen ...
    */

    e1->xPos = 5;

    return 0;
}


so gibt der Compiler mir die Fehlermeldung aus:
1>d:\c++ projekte\wichtige_uebungen\pointerpointerfunctest\main.cpp(49) : error C2227: Links von "->xPos" muss sich ein Zeiger auf Klassen-/Struktur-/Union-/generischen Typ befinden.

Pointer auf Pointer sind gut um Pointer mit Adressen zu füllen, aber was bringt es mir Adressen dort rein zu schreiben, wenn ich doch einfach einen einzigen Pointer haben kann in dem ich die Adresse ebenfalls hineinschreiben kann. Es ist doch nur Speicherverschwendung einen zweiten Pointer zu benutzen oder? ... Verwirrt :S

patrick246

Treue Seele

Beiträge: 328

Wohnort: nahe Heilbronn/BW

Beruf: TG Profil Informatik-Schüler

  • Private Nachricht senden

30

13.04.2013, 16:21

C-/C++-Quelltext

1
(*e1)->xPos = 5;

Erklärung: e1 verweist auf einen Pointer und dieser Pointer verweist wieder auf ein Enemy-Objekt. Wenn du nun e1 dereferenzierst ( *(e1) ), dann kannst du über den -> Operator darauf zugreifen. Der Dereferenzierungsoperator liefert ein Enemy* zurück und der -> Operator greift auf dessen Elemente zu.

Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von »patrick246« (13.04.2013, 16:34) aus folgendem Grund: Tippfehler, siehe Beitrag weiter unten


Werbeanzeige