Pointer
-
Noch etwas:
Du schreibst etwas von einer Nachricht, auf die der Pointer "mailbox" zeigt. Ist die Nachricht wirklich nur ein Zeichen lang? in der Variablen "variable" kann nämlich nur ein Zeichen gespeichert werden.
Hier mal dein verbesserter Code:
void *mailbox = NULL; // hier sollte man dem Pointer noch NULL zuweisen. unsigned char variable; variable = 0; // NULL nur für Pointer verwenden while (1) { mailbox = /*Pointer auf eine Nachricht*/; if (mailbox != NULL) //(void *)0 ginge auch, siehe Definition von NULL { //if(variable == 0) <- If-Bedingung unnötig, da variable kein Pointer. //{ variable = *((unsigned char*)(mailbox)); // Derefernzierung von mailbox, vorher nach unsigned char casten. //} } } // gehört zur while-schleife ;)
Wie ich schon geschrieben habe, enthält "variable" das erste Zeichen, auf das der pointer "mailbox" zeigt. War das in deinem Sinne?
-
Oder meinst du
unsigned char *variable;
?
-
Danke für die Hilfe.
Ja es ist nur ein Zeichen lang. zb. 0,1,2,3,. Vielleicht ändere ich es noch in ein int. Aber da Zeichen versendet werden dachte ich dass char besser wäre.
NULL war bisschen falsch ausgedrückt. Das ist ein define mit dem Inhalt 0.
zb. #define XXX 0
das andere war
if(variable == XXX) { variable = YYY; }
Das ist mir bisschen unklar wie ist das genau beschrieben. ((unsigned char)(mailbox))
Mailbox ist ein Pointer. Das hat eine Adresse gespeichert. Mit *mailbox greif ich auf den Inhalt der Adresse. Was bedeutet genau "unsigned char*"
-
Ein char ist idR. i Byte groß. Damit kannst du Werte von -128 bis +127 speichern. unsigned bedeutet, dass keine Vorzeichen gespeichert werden, in einem unsigned char kann man also Werte von 0-255 speichern.
((unsigned char)(mailbox))
zunächst castest du den void-pointer "mailbox" mittels "(unsigned char*)(mailbox)" in einen pointer auf unsigned char. Das muss so sein, da "variable" den Datentyp unsigned char hat. Dann musst du den gecasteten Pointer noch dereferenzieren. Daher auch der * vor der ersten Klammer.Einfacher wäre es, wenn du den Pointer "mailbox" gleich als pointer auf unsigned char deklarierst.
NULL ist in C auch nicht einfach als 0 deklariert, sondern als (void*)0, Es handelt sich also um einen void-Zeiger, der auf die Adresse 0 Zeigt.
-
Danke für die Erklärung.
Somit könnte ich es auch so schreiben.
unsigned char *mailbox; variable = *mailbox;
-
Pointi schrieb:
Danke für die Erklärung.
Somit könnte ich es auch so schreiben.
unsigned char *mailbox; variable = *mailbox;
Richtig
-
Was mich noch interessiert.
Kann man auch schreiben (char mailbox) oder braucht man die Klammern.
So wäre mailbox ein Pointer und mit dem * vorne greif ich auf den Inhalt.
-
Du meinst bei der Deklaration? Also so?
int main() { *(char *x) = 5; }
Das wäre schlecht, da x ja auf nichts bestimmtes zeigt. Theoretisch sinnvoll wäre vielleicht
int main() { char y; *(char *x = &y) = 5; }
Aber auch das ist nicht möglich.
Edit:
Ach so, bezog sich vermutlich auf den Vorpost daOk, nein man kann die Klammer nicht weg lassen, da das ein Cast auf einen anderen Typ ist. Casts solltest du bereits kennengelernt haben? Ansonsten:
http://home.fhtw-berlin.de/~junghans/cref/CONCEPT/cast.htmlHier wird ein void* in einen unsigned char* gecastet; ein void* kann nicht dereferenziert werden da void kein (vollständiger) Typ ist.
-
Hallo
habe noch eine Frage. Wird bei diesem Beispiel nicht die Adresse überschrieben. Ich schicke variable. Mit &zahl wird ja auf die Adresse von variable zugegriffen. Wird somit nicht die Adresse von Variable auf 10 gesetzt?
MfG
void set(int &zahl) { zahl = 10; } int main() { int variable = 5; set(variable); }
-
In C ist der Code nicht legal, in C++ würde das funktionieren - das nennt sich dann "Referenzen".
-
Das Beispiel sollte gar nicht Kompilieren.
void set(int *zahl) { *zahl = 10; } int main() { int variable = 5; set(&variable); }
Vermutlich nutzt du einen C++ Compiler. Bei dem stellt das
void set(int &zahl)
eine Referenz dar, das ist aber ein anderes Thema und kein C!
-
Bei diesem Bsp wird die Adresse von Variable verschickt. *zahl ist ein Pointer. In zahl wird die Adresse von variable gespeichert und bei *zahl greif ich auf den Inhalt der Adresse.
void set(int *zahl) { *zahl = 10; } int main() { int variable = 5; set(&variable); }
Was wird aber hier übergeben. Ich schicke die Adresse und mit *zahl greif ich auf den Inhalt der Adresse
void set(int zahl) { *zahl = 10; } int main() { int variable = 5; set(&variable); }
-
Das zweite Beispiel wird auch nicht kompilieren. Theoretisch vielleicht mit ganz üblen Hacks:
void set(int zahl) { *((int*)zahl) = 10; } int main() { int variable = 5; set((int)&variable); }
Aber das das ist nicht standardkonform, da nicht garantiert wird, dass sizeof(int*) == sizeof(int). Nicht machen! Böse!
-
Pointi schrieb:
Was wird aber hier übergeben. Ich schicke die Adresse und mit *zahl greif ich auf den Inhalt der Adresse
void set(int zahl) { *zahl = 10; } int main() { int variable = 5; set(&variable); }
Das dürte nicht einmal durch den Compiler kommen - du übergibst erstens einen Pointer an eine Funktion, die einen int erwartet, und versuchst zweitens, diesen int zu dereferenzieren.
-
Hoffentlich habe ich es jetzt richtig verstanden.
Wenn &variable steht muss auch *zahl stehen.
`void set(int *zahl)
{
*zahl = 10;
}
int main()
{
int variable = 5;
set(&variable);
}`
Das funktioniert nicht
`void set(int *zahl)
{
*zahl = 10;
}
int main()
{
int variable = 5;
set(variable);
}`
und das funktioniert nicht
`void set(int *zahl)
{
*zahl = 10;
}
int main()
{
int variable = 5;
set(&variable);
}`
So greife ich auf den Inhalt
`void set(int *zahl)
{
*zahl = 10;
}
int main()
{
int variable = 5;
set(&variable);
}`
und so ändere ich die Adresse von variable
`void set(int *zahl)
{
zahl = 10;
}
int main()
{
int variable = 5;
set(&variable);
}`
-
Du hast dich einmal vertippt und
zahl = 10
ist nicht unbedingt sinnvoll. Trotzdem denke ich, du hast das Prinzip verstanden. Nur muss man das doch nicht alles auswendig lernen oO&variable <- Steht für die Adresse von "variable".
int *p; <- Ist ein Pointer.p = x; // Ist von der Syntax her nichts anderes wie
x = 5; // und ändert einfach nur den Wert der Variablen selbst.*p = 5; // Greift auf den Wert der Variablen die an der Adresse steht auf die p zeigt zu.
Ich glaube ich schreibe mal ein C Tutorial, es scheint ja noch nicht genug zu geben
-
Pointi schrieb:
und das funktioniert nicht
void set(int *zahl)
{
*zahl = 10;
}int main()
{
int variable = 5;
set(&variable);
}Das müsste funktionieren. Es sei denn, ich übersehe im Moment etwas.
Pointi schrieb:
und so ändere ich die Adresse von variable
void set(int *zahl)
{
zahl = 10;
}int main()
{
int variable = 5;
set(&variable);
}Das ist Böse, da du nicht weisst, was an der Adresse 10 zu finden ist. Wenn du dann an die Stelle im Speicher schreibst, knallts.
(EDIT: Ich sehe gerade, Hier änderst du gar nicht die Adresse von "variable", nur die Adresse der Variablen "zahl" aus der Funktion. Das ist ein temporäres Objekt. ändert aber nichts an der Tatsache, dass das Pfusch ist.)Edit2: Man kann meines Wissens nur Adressen von Zeigern ändern, nicht jedoch von "normalen" Variablen. Oh mann, ich schreibe heute wieder schneller als ich denken kann
Das dürfte aber auch nicht ohne Hacks funktionieren, das könnte eventuell gehen:
//So ändert man dann Adressen von Zeigern: void set(int** var) { *var = (int*)0x01234567; // Pfusch! } int main() { int* variable; set(&variable); // Pfusch! }
Aber merke: Nie die Adressen manuell zuweisen.
(Wir programmieren ja schließlich keine Treiber)
-
Das müsste funktionieren. Es sei denn, ich übersehe im Moment etwas.
Hatte einen kleinen Tippfehler.
ist nicht unbedingt sinnvoll. Trotzdem denke ich, du hast das Prinzip verstanden. Nur muss man das doch nicht alles auswendig lernen oO
Naja, ich lern es auch nicht auswendig sondern versuche zu verstehen was in welchem Fall passiert.
Ändere ich hier die Adresse von variable oder würde das auch nicht funktioneren da &variable und int *zahl stehen muss.
void set(int zahl) { zahl = 10; } int main() { int variable = 5; set(&variable); }
Inwieweit unterscheiden sich diese zwei.
Hier erzeuge ich einen Pointer und die Adresse vom Pointer setze ich auf 10.
int *var; var = 10;
int *var; var = (int*)10;
-
Pointi schrieb:
Hatte einen kleinen Tippfehler.
I'm da Hellseear
Pointi schrieb:
Ändere ich hier die Adresse von variable oder würde das auch nicht funktioneren da &variable und int *zahl stehen muss.
void set(int zahl) { zahl = 10; } int main() { int variable = 5; set(&variable); }
Wenn die Funktion aufgerufen wird, ist zahl = &variable. Dann setzt du zahl = 10. Macht aber halt keinen Sinn
Pointi schrieb:
Inwieweit unterscheiden sich diese zwei.
Es ist sehr unüblich Pointern einfach "irgendwelche" Werte zuzuweisen. (z.B. 10). Deshalb wird ein guter Compiler hier warnen, es sei denn du "castest" den Wert 10 in den Typ int*, damit sagst du dem Compiler quasi "ich weiß was ich hier mache!".
-
Pointi schrieb:
Ändere ich hier die Adresse von variable oder würde das auch nicht funktioneren da &variable und int *zahl stehen muss.
Das Funktioniert nicht, da hab ich in meinem letzen Post was zu geschrieben.
Pointi schrieb:
Inwieweit unterscheiden sich diese zwei.
Hier erzeuge ich einen Pointer und die Adresse vom Pointer setze ich auf 10.
Bei dem zweiten Beispiel ist noch ein Cast dabei, der dem Compiler sagen soll, dass die Zahl als Adresse interpretiert werden soll. Die erste Möglichkeit dürfte eigentlich nicht kompiliert werden.
Edit: Ich sags nochmal: Normalerweise muss man den den Zeigern keine bestimmten Adressen "manuell" zuweisen. Das kann mal vorkommen, wenn man Treiber o.ä. progrmmiert. Normalweise ändert man die Adressen wenn überhaupt so:
int a,b; int *ptr; a=10; ptr = &a; *ptr = 5; // a ist jetzt 5 ptr = &b; *ptr = 5; // b ist jetzt auch 5 int* ptr2 = ptr; // ptr2 zeigt jetzt auch auf b