Die Struktur, Die Übergabe und der Doppelpointer
-
Guten Morgen Jungs,
ich habe mal wieder ne Frage, bzw. Verständnissfragen.
ACHTUNG, das hier wird länger.Also ich habe eine Struktur die 4-5 Int Elemente enthält. ( In den folgenden Codebeispielen 4 INT , sonst nichts). Ich will und kann kein Array nehmen, da die Struktur später mal noch 2-3 Strings enthalten wird. Ausserdem wäre das ganze mit einem Array oder noch anders, bestimmt einfacher zu lösen, aber "einfach" ist einfach zu einfach :-).
So, hier mal der Strukturaufbau und die def. von home und null (Normalerweise schreib ich typedef´s groß, habs hier einfach schnell schnell vergessen. )
#include <stdio.h> #include <stdlib.h> #include <string.h> #define si_max 4 struct data {int v1; int v2; int v3; int v4;}; typedef struct data rs; void init (rs *home, rs*null); void init2 (int **home, int **null); rs home, null;
Wie man hier schon erkennen kann, ich hab 2 Funktionen zum initilisieren der Strukturen.
die erste :
#include <stdio.h> #include <stdlib.h> #include "system.h" void init (rs *home, rs*null){ int *hptr, *nptr, i; size_t max; max= si_max; hptr=&home->v1; nptr=&null->v1; for (i=0; i<max; i++){ *hptr=0; *nptr=0; hptr++; nptr++; } }
Ich schreibe jetzt mal die Beschreibung wie von SeppJ gelernt, also :
home und null sind Zeiger auf meine Struct RS.
hptr und nptr sind normale Zeiger auf int, die auf das erste element von rs zeigen.
somit kann ich mit *hptr den Wert ändern und mit hptr++ die Adresse erhöhen, damit mein Zeiger auf das nächste "Strukturelement" bzw. nächste Int zeigt.
Stimmt soweit? Funktioniert bei mir ohne Warnung oder sonst etwas mit folgendem Aufruf:aus main.c
init(&home, &null);
Aufruf ist mir klar.
So, Frage 1: Kann man das nicht eleganter lösen? Bei einem übergebenen Array, ist doch der Name Zeiger auf das Erste element.
Wie sieht das mit einer Struktur aus? Ein Zeiger auf Struct, müsste der nicht auch prizipiell auf das erste Element, die Startadresse zeigen?
Könnte ich diesen "ZEiger" nicht dereferenzieren , Wert zuweisen , Zeiger erhöhen auf das "Zweite" element? Wenn ja, wie?Und hier die 2 Funktion, versucht mit "Doppelzeiger".
init2.c :#include <stdio.h> #include <stdlib.h> #include "system.h" void init2 (int **home, int **null){ int i, j=0; for (i=0; i<si_max; i++){ **home=j; **null=j; j+=3; (*home)++; (*null)++; } }
Ok, let´s get it on. Home und Null sind Zeiger, die auf einen Zeiger, der auf einen INt zeigt zeigen.
Ich kann mit **home den Wert des "ursprünglichen" Elements ändern, da mein Home zeiger auf einen Zeiger zeigt, den ich so manipuliere .
mit (*home)++ kann ich meinen Zeiger erhöhen, damit er auf das 2. Element zeigt . Ich will meinen Zeiger erhöhen, nich den "ursprünglichen", der ja immer noch auf das erste INT zeigen soll.
Richtig soweit?Aufruf in Main usw wie folgt:
int main(int argc, char *argv[]) { int *hp, *np; hp = &home.v1; np = &null.v1; init2(&hp, &np); }
So, ich habe den Aufruf hingebastelt, mir ist nicht klar warum ich die Adresse und nicht den Zeiger übergeben muss. Oder nicht ganz klar .
Auch hier stellt sich mir die Frage wie bei Funktion 1 , kann ich das nicht irgendwie mit "ZEiger auf Struktur" lösen?
Also etwa so:
PSEUDOCODE:
rs *home*home =0; //erstes Element oder wie auch immer
home++ // Adresse erhöhen auf 2 .ElementSchon mal Danke , an Alle, die bis hier gelesen haben
-
Zu Frage 1:
Ein struct ist kein Array. Somit ist die Antwort Nein.Du kannst structs auch einander zuweisen:
home = null;
beginner88888 schrieb:
mir ist nicht klar warum ich die Adresse und nicht den Zeiger übergeben muss.
Weil du einen Zeiger auf int hast, die Funktion aber einen Zeiger auf einen Zeiger auf int haben möchte.
rs *home; //hier fehlt die Zuweisung von home. *home =0; // *home ist eine struct. Also musst du auch eine struct zuweisen home++ // Hier zeigt home auf die nächste struct (z.B. bei einem Array of struct)
In einer struct können auch Padding-Bytes (Füllbyte) sein. Du kannst nicht davon ausgehen, das verschiedene Elemente direkt hintereinander im Speicher stehen.
-
allo Dirk, danke für die Antworten.
OK, das mit der Adresse übergeben bei dem Doppelzeiger ist mir jetzt klar.Generell, mit der Padding-Byte Sache... Solche Funktionen zum "init" machen wie ich probiert habe, sollte man dann wohl eher in der "experimentieren" Ecke lassen und nicht verwenden?
Nochmal wegen dem Zeiger auf Struct... OK, sehe ein es geht einfach nicht, aber auf was zeigt der Zeiger denn dann, adressentypisch? Nicht auch auf eine Art "Startadresse"? Rest vom Code kann man so lassen?
-
Die Adresse von der struct fällt schon mit der Adresse vom ersten Element zusammen.
Nur, ist das dann (bei dir) einrs*
. Das erste Element hatint*
.
Das sind unterschiedliche Zeiger.beginner88888 schrieb:
, sollte man dann wohl eher in der "experimentieren" Ecke lassen und nicht verwenden?
So ist es.
Du gewinnst dadurch nichts.
Rest vom Code kann man so lassen?
Welchen Rest? Das ist doch alles experimentell.
-
So beim oberflächlichen Lesen hab ich das Gefühl, du willst eigentlich
struct data { int v[4]; /* Rest */ };
oder?
-
Ja, mit "Rest" war gemeint ob das mit dem Doppelpointer so passt, oder ob man das generell "anders" macht.
-
@Bashar, das wäre zwar das gleiche, aber genau das wollte ich nicht
Vor allem will ich die Struktur-elemente später namentlich ansprechen und nicht mir Array Index arbeiten.Wie gesagt, die Struktur ist jettz auf das wesentliche begrenzt, soll mal so werden:
struct RS{int ID; int X; int Y; int Z; float Offset_lin; float Offset_Circ; int Status; bool Turn; char *PTP-Name; char *Err_MSG};
RS HOME, NULLFRAME;
bla bla bla
-
So, jetzt hat sich noch ne andere Unklarheit ergeben...
Und zwar habe ich jetzt ein Array of Struct, das ich übergeben will
rs buffer[50]
das "speichern" will ich in ner extra funktion machen.
Ich dachte daran einen Zeiger auf die Struktur zu übergeben , seh aber irgendwie den Wald vor lauter Bäumen nichtfoo(rs uebergabe[50]) //übergibt ... Werden Arrays nicht eh "by Reference" übergeben foo(rs *zeiger, size_t anzahl, FILE *datzeiger){ // beim Aufruf reicht dann der Array-name, da er Zeiger auf das erste Elemnt ist...? int i; for (i=0; i<anzahl, i++){ fwrite(zeiger, sizeof(rs), 1, datzeiger); zeiger++; // sollte meinen Zeiger auf das nächste Array Element erhöhen? } ???????????
Steh gerade voll auf dem Schlauch.
-
Noch etwas OFF-Topic :
Warum funktioniert das :
do { puts("Wert eingben: \n"); scanf("%d", &i); }while ( ! ( (i==3) || (i==4)) );
Aber
do { puts("Wert eingben: \n"); scanf("%d", &i); }while ( (i!=3) || (i!=4) );
...bricht die Schleife nicht ab??
while i not 3 or i not 4 ...
-
Zu dem "Steh gerade voll auf dem Schlauch."
Ersetze die ??????????? durch }
Oder was hast du noch vor?Du kannst auch alles auf einmal schreiben:
fwrite(zeiger, sizeof(rs), anzahl, datzeiger);
Zu OT:
Wenn du das ! in den Ausdruck reinziehst, musst du auch dsas || in && wandeln (und umgekehrt)wenn i == 3 ist, dann ist der 3 != 4 (der zweite Ausdruck) wahr
wenn i == 4 ist, dann ist der 4 != 3 (der erste Ausdruck )wahr
Bei allen anderen Zahlen sowieso. Also ist es immer wahr.
-
Hmm... dann war der Schlauch doch nicht so groß
foo(rs uebergabe[50])
Bei dieser Methode müsste ich dann mit Index arbeiten oder?
Danke für den Tipp bzw. die Lösung meines Logik-Problems.
Jezt wo du es "ausführlich" geschrieben hast, ist es eigentlich klar, warum die Schleife nicht abgebrochen wird.Danke!!
-
beginner88888 schrieb:
foo(rs uebergabe[50])
Bei dieser Methode müsste ich dann mit Index arbeiten oder?
Nein!
Zwischen
foo(rs uebergabe[50]) {...}
und
foo(rs *uebergabe) {...}
gibt es keinen Unterschied.
Du hast keine Information darüber, wie groß der Bereich/Array ist, auf den uebergabe zeigt.Zudem kannst du jederzeit zwischen Array- und Pointerschreibweise wechseln.
Denn wenn der Compiler im COde
uebergabe[10]
findet, macht er gleich*(uebergabe+10)
daraus.